Index: head/gnu/usr.bin/perl/perl/arg.h =================================================================== --- head/gnu/usr.bin/perl/perl/arg.h (revision 2652) +++ head/gnu/usr.bin/perl/perl/arg.h (revision 2653) @@ -1,994 +1,997 @@ -/* $RCSfile: arg.h,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:34 $ +/* $RCSfile: arg.h,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:34 $ * * Copyright (c) 1991, Larry Wall * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. * * $Log: arg.h,v $ + * Revision 1.1.1.1 1994/09/10 06:27:34 gclarkii + * Initial import of Perl 4.046 bmaked + * * Revision 1.1.1.1 1993/08/23 21:29:34 nate * PERL! * * Revision 4.0.1.3 92/06/08 11:44:06 lwall * patch20: O_PIPE conflicted with Atari * patch20: clarified debugging output for literals and double-quoted strings * * Revision 4.0.1.2 91/11/05 15:51:05 lwall * patch11: added eval {} * patch11: added sort {} LIST * * Revision 4.0.1.1 91/06/07 10:18:30 lwall * patch4: length($`), length($&), length($') now optimized to avoid string copy * patch4: new copyright notice * patch4: many, many itty-bitty portability fixes * * Revision 4.0 91/03/20 01:03:09 lwall * 4.0 baseline. * */ #define O_NULL 0 #define O_RCAT 1 #define O_ITEM 2 #define O_SCALAR 3 #define O_ITEM2 4 #define O_ITEM3 5 #define O_CONCAT 6 #define O_REPEAT 7 #define O_MATCH 8 #define O_NMATCH 9 #define O_SUBST 10 #define O_NSUBST 11 #define O_ASSIGN 12 #define O_LOCAL 13 #define O_AASSIGN 14 #define O_SASSIGN 15 #define O_CHOP 16 #define O_DEFINED 17 #define O_UNDEF 18 #define O_STUDY 19 #define O_POW 20 #define O_MULTIPLY 21 #define O_DIVIDE 22 #define O_MODULO 23 #define O_ADD 24 #define O_SUBTRACT 25 #define O_LEFT_SHIFT 26 #define O_RIGHT_SHIFT 27 #define O_LT 28 #define O_GT 29 #define O_LE 30 #define O_GE 31 #define O_EQ 32 #define O_NE 33 #define O_NCMP 34 #define O_BIT_AND 35 #define O_XOR 36 #define O_BIT_OR 37 #define O_AND 38 #define O_OR 39 #define O_COND_EXPR 40 #define O_COMMA 41 #define O_NEGATE 42 #define O_NOT 43 #define O_COMPLEMENT 44 #define O_SELECT 45 #define O_WRITE 46 #define O_DBMOPEN 47 #define O_DBMCLOSE 48 #define O_OPEN 49 #define O_TRANS 50 #define O_NTRANS 51 #define O_CLOSE 52 #define O_EACH 53 #define O_VALUES 54 #define O_KEYS 55 #define O_LARRAY 56 #define O_ARRAY 57 #define O_AELEM 58 #define O_DELETE 59 #define O_LHASH 60 #define O_HASH 61 #define O_HELEM 62 #define O_LAELEM 63 #define O_LHELEM 64 #define O_LSLICE 65 #define O_ASLICE 66 #define O_HSLICE 67 #define O_LASLICE 68 #define O_LHSLICE 69 #define O_SPLICE 70 #define O_PUSH 71 #define O_POP 72 #define O_SHIFT 73 #define O_UNPACK 74 #define O_SPLIT 75 #define O_LENGTH 76 #define O_SPRINTF 77 #define O_SUBSTR 78 #define O_PACK 79 #define O_GREP 80 #define O_JOIN 81 #define O_SLT 82 #define O_SGT 83 #define O_SLE 84 #define O_SGE 85 #define O_SEQ 86 #define O_SNE 87 #define O_SCMP 88 #define O_SUBR 89 #define O_DBSUBR 90 #define O_CALLER 91 #define O_SORT 92 #define O_REVERSE 93 #define O_WARN 94 #define O_DIE 95 #define O_PRTF 96 #define O_PRINT 97 #define O_CHDIR 98 #define O_EXIT 99 #define O_RESET 100 #define O_LIST 101 #define O_EOF 102 #define O_GETC 103 #define O_TELL 104 #define O_RECV 105 #define O_READ 106 #define O_SYSREAD 107 #define O_SYSWRITE 108 #define O_SEND 109 #define O_SEEK 110 #define O_RETURN 111 #define O_REDO 112 #define O_NEXT 113 #define O_LAST 114 #define O_DUMP 115 #define O_GOTO 116 #define O_INDEX 117 #define O_RINDEX 118 #define O_TIME 119 #define O_TMS 120 #define O_LOCALTIME 121 #define O_GMTIME 122 #define O_TRUNCATE 123 #define O_LSTAT 124 #define O_STAT 125 #define O_CRYPT 126 #define O_ATAN2 127 #define O_SIN 128 #define O_COS 129 #define O_RAND 130 #define O_SRAND 131 #define O_EXP 132 #define O_LOG 133 #define O_SQRT 134 #define O_INT 135 #define O_ORD 136 #define O_ALARM 137 #define O_SLEEP 138 #define O_RANGE 139 #define O_F_OR_R 140 #define O_FLIP 141 #define O_FLOP 142 #define O_FORK 143 #define O_WAIT 144 #define O_WAITPID 145 #define O_SYSTEM 146 #define O_EXEC_OP 147 #define O_HEX 148 #define O_OCT 149 #define O_CHOWN 150 #define O_KILL 151 #define O_UNLINK 152 #define O_CHMOD 153 #define O_UTIME 154 #define O_UMASK 155 #define O_MSGGET 156 #define O_SHMGET 157 #define O_SEMGET 158 #define O_MSGCTL 159 #define O_SHMCTL 160 #define O_SEMCTL 161 #define O_MSGSND 162 #define O_MSGRCV 163 #define O_SEMOP 164 #define O_SHMREAD 165 #define O_SHMWRITE 166 #define O_RENAME 167 #define O_LINK 168 #define O_MKDIR 169 #define O_RMDIR 170 #define O_GETPPID 171 #define O_GETPGRP 172 #define O_SETPGRP 173 #define O_GETPRIORITY 174 #define O_SETPRIORITY 175 #define O_CHROOT 176 #define O_FCNTL 177 #define O_IOCTL 178 #define O_FLOCK 179 #define O_UNSHIFT 180 #define O_REQUIRE 181 #define O_DOFILE 182 #define O_EVAL 183 #define O_FTRREAD 184 #define O_FTRWRITE 185 #define O_FTREXEC 186 #define O_FTEREAD 187 #define O_FTEWRITE 188 #define O_FTEEXEC 189 #define O_FTIS 190 #define O_FTEOWNED 191 #define O_FTROWNED 192 #define O_FTZERO 193 #define O_FTSIZE 194 #define O_FTMTIME 195 #define O_FTATIME 196 #define O_FTCTIME 197 #define O_FTSOCK 198 #define O_FTCHR 199 #define O_FTBLK 200 #define O_FTFILE 201 #define O_FTDIR 202 #define O_FTPIPE 203 #define O_FTLINK 204 #define O_SYMLINK 205 #define O_READLINK 206 #define O_FTSUID 207 #define O_FTSGID 208 #define O_FTSVTX 209 #define O_FTTTY 210 #define O_FTTEXT 211 #define O_FTBINARY 212 #define O_SOCKET 213 #define O_BIND 214 #define O_CONNECT 215 #define O_LISTEN 216 #define O_ACCEPT 217 #define O_GHBYNAME 218 #define O_GHBYADDR 219 #define O_GHOSTENT 220 #define O_GNBYNAME 221 #define O_GNBYADDR 222 #define O_GNETENT 223 #define O_GPBYNAME 224 #define O_GPBYNUMBER 225 #define O_GPROTOENT 226 #define O_GSBYNAME 227 #define O_GSBYPORT 228 #define O_GSERVENT 229 #define O_SHOSTENT 230 #define O_SNETENT 231 #define O_SPROTOENT 232 #define O_SSERVENT 233 #define O_EHOSTENT 234 #define O_ENETENT 235 #define O_EPROTOENT 236 #define O_ESERVENT 237 #define O_SOCKPAIR 238 #define O_SHUTDOWN 239 #define O_GSOCKOPT 240 #define O_SSOCKOPT 241 #define O_GETSOCKNAME 242 #define O_GETPEERNAME 243 #define O_SSELECT 244 #define O_FILENO 245 #define O_BINMODE 246 #define O_VEC 247 #define O_GPWNAM 248 #define O_GPWUID 249 #define O_GPWENT 250 #define O_SPWENT 251 #define O_EPWENT 252 #define O_GGRNAM 253 #define O_GGRGID 254 #define O_GGRENT 255 #define O_SGRENT 256 #define O_EGRENT 257 #define O_GETLOGIN 258 #define O_OPEN_DIR 259 #define O_READDIR 260 #define O_TELLDIR 261 #define O_SEEKDIR 262 #define O_REWINDDIR 263 #define O_CLOSEDIR 264 #define O_SYSCALL 265 #define O_PIPE_OP 266 #define O_TRY 267 #define O_EVALONCE 268 #define MAXO 269 #ifndef DOINIT extern char *opname[]; #else char *opname[] = { "NULL", "RCAT", "ITEM", "SCALAR", "ITEM2", "ITEM3", "CONCAT", "REPEAT", "MATCH", "NMATCH", "SUBST", "NSUBST", "ASSIGN", "LOCAL", "AASSIGN", "SASSIGN", "CHOP", "DEFINED", "UNDEF", "STUDY", "POW", "MULTIPLY", "DIVIDE", "MODULO", "ADD", "SUBTRACT", "LEFT_SHIFT", "RIGHT_SHIFT", "LT", "GT", "LE", "GE", "EQ", "NE", "NCMP", "BIT_AND", "XOR", "BIT_OR", "AND", "OR", "COND_EXPR", "COMMA", "NEGATE", "NOT", "COMPLEMENT", "SELECT", "WRITE", "DBMOPEN", "DBMCLOSE", "OPEN", "TRANS", "NTRANS", "CLOSE", "EACH", "VALUES", "KEYS", "LARRAY", "ARRAY", "AELEM", "DELETE", "LHASH", "HASH", "HELEM", "LAELEM", "LHELEM", "LSLICE", "ASLICE", "HSLICE", "LASLICE", "LHSLICE", "SPLICE", "PUSH", "POP", "SHIFT", "UNPACK", "SPLIT", "LENGTH", "SPRINTF", "SUBSTR", "PACK", "GREP", "JOIN", "SLT", "SGT", "SLE", "SGE", "SEQ", "SNE", "SCMP", "SUBR", "DBSUBR", "CALLER", "SORT", "REVERSE", "WARN", "DIE", "PRINTF", "PRINT", "CHDIR", "EXIT", "RESET", "LIST", "EOF", "GETC", "TELL", "RECV", "READ", "SYSREAD", "SYSWRITE", "SEND", "SEEK", "RETURN", "REDO", "NEXT", "LAST", "DUMP", "GOTO",/* shudder */ "INDEX", "RINDEX", "TIME", "TIMES", "LOCALTIME", "GMTIME", "TRUNCATE", "LSTAT", "STAT", "CRYPT", "ATAN2", "SIN", "COS", "RAND", "SRAND", "EXP", "LOG", "SQRT", "INT", "ORD", "ALARM", "SLEEP", "RANGE", "FLIP_OR_RANGE", "FLIP", "FLOP", "FORK", "WAIT", "WAITPID", "SYSTEM", "EXEC", "HEX", "OCT", "CHOWN", "KILL", "UNLINK", "CHMOD", "UTIME", "UMASK", "MSGGET", "SHMGET", "SEMGET", "MSGCTL", "SHMCTL", "SEMCTL", "MSGSND", "MSGRCV", "SEMOP", "SHMREAD", "SHMWRITE", "RENAME", "LINK", "MKDIR", "RMDIR", "GETPPID", "GETPGRP", "SETPGRP", "GETPRIORITY", "SETPRIORITY", "CHROOT", "FCNTL", "SYSIOCTL", "FLOCK", "UNSHIFT", "REQUIRE", "DOFILE", "EVAL", "FTRREAD", "FTRWRITE", "FTREXEC", "FTEREAD", "FTEWRITE", "FTEEXEC", "FTIS", "FTEOWNED", "FTROWNED", "FTZERO", "FTSIZE", "FTMTIME", "FTATIME", "FTCTIME", "FTSOCK", "FTCHR", "FTBLK", "FTFILE", "FTDIR", "FTPIPE", "FTLINK", "SYMLINK", "READLINK", "FTSUID", "FTSGID", "FTSVTX", "FTTTY", "FTTEXT", "FTBINARY", "SOCKET", "BIND", "CONNECT", "LISTEN", "ACCEPT", "GHBYNAME", "GHBYADDR", "GHOSTENT", "GNBYNAME", "GNBYADDR", "GNETENT", "GPBYNAME", "GPBYNUMBER", "GPROTOENT", "GSBYNAME", "GSBYPORT", "GSERVENT", "SHOSTENT", "SNETENT", "SPROTOENT", "SSERVENT", "EHOSTENT", "ENETENT", "EPROTOENT", "ESERVENT", "SOCKPAIR", "SHUTDOWN", "GSOCKOPT", "SSOCKOPT", "GETSOCKNAME", "GETPEERNAME", "SSELECT", "FILENO", "BINMODE", "VEC", "GPWNAM", "GPWUID", "GPWENT", "SPWENT", "EPWENT", "GGRNAM", "GGRGID", "GGRENT", "SGRENT", "EGRENT", "GETLOGIN", "OPENDIR", "READDIR", "TELLDIR", "SEEKDIR", "REWINDDIR", "CLOSEDIR", "SYSCALL", "PIPE", "TRY", "EVALONCE", "269" }; #endif #define A_NULL 0 #define A_EXPR 1 #define A_CMD 2 #define A_STAB 3 #define A_LVAL 4 #define A_SINGLE 5 #define A_DOUBLE 6 #define A_BACKTICK 7 #define A_READ 8 #define A_SPAT 9 #define A_LEXPR 10 #define A_ARYLEN 11 #define A_ARYSTAB 12 #define A_LARYLEN 13 #define A_GLOB 14 #define A_WORD 15 #define A_INDREAD 16 #define A_LARYSTAB 17 #define A_STAR 18 #define A_LSTAR 19 #define A_WANTARRAY 20 #define A_LENSTAB 21 #define A_MASK 31 #define A_DONT 32 /* or this into type to suppress evaluation */ #ifndef DOINIT extern char *argname[]; #else char *argname[] = { "A_NULL", "EXPR", "CMD", "STAB", "LVAL", "LITERAL", "DOUBLEQUOTE", "BACKTICK", "READ", "SPAT", "LEXPR", "ARYLEN", "ARYSTAB", "LARYLEN", "GLOB", "WORD", "INDREAD", "LARYSTAB", "STAR", "LSTAR", "WANTARRAY", "LENSTAB", "22" }; #endif #ifndef DOINIT extern bool hoistable[]; #else bool hoistable[] = {0, /* A_NULL */ 0, /* EXPR */ 1, /* CMD */ 1, /* STAB */ 0, /* LVAL */ 1, /* SINGLE */ 0, /* DOUBLE */ 0, /* BACKTICK */ 0, /* READ */ 0, /* SPAT */ 0, /* LEXPR */ 1, /* ARYLEN */ 1, /* ARYSTAB */ 0, /* LARYLEN */ 0, /* GLOB */ 1, /* WORD */ 0, /* INDREAD */ 0, /* LARYSTAB */ 1, /* STAR */ 1, /* LSTAR */ 1, /* WANTARRAY */ 0, /* LENSTAB */ 0, /* 21 */ }; #endif union argptr { ARG *arg_arg; char *arg_cval; STAB *arg_stab; SPAT *arg_spat; CMD *arg_cmd; STR *arg_str; HASH *arg_hash; }; struct arg { union argptr arg_ptr; short arg_len; unsigned short arg_type; unsigned short arg_flags; }; #define AF_ARYOK 1 /* op can handle multiple values here */ #define AF_POST 2 /* post *crement this item */ #define AF_PRE 4 /* pre *crement this item */ #define AF_UP 8 /* increment rather than decrement */ #define AF_COMMON 16 /* left and right have symbols in common */ #define AF_DEPR 32 /* an older form of the construct */ #define AF_LISTISH 64 /* turn into list if important */ -#define AF_LOCAL 128 /* list of local variables */ +#define AF_LOCAL_XX 128 /* list of local variables */ /* * Most of the ARG pointers are used as pointers to arrays of ARG. When * so used, the 0th element is special, and represents the operator to * use on the list of arguments following. The arg_len in the 0th element * gives the maximum argument number, and the arg_str is used to store * the return value in a more-or-less static location. Sorry it's not * re-entrant (yet), but it sure makes it efficient. The arg_type of the * 0th element is an operator (O_*) rather than an argument type (A_*). */ #define Nullarg Null(ARG*) #ifndef DOINIT EXT unsigned short opargs[MAXO+1]; #else #define A(e1,e2,e3) (e1+(e2<<2)+(e3<<4)) #define A5(e1,e2,e3,e4,e5) (e1+(e2<<2)+(e3<<4)+(e4<<6)+(e5<<8)) unsigned short opargs[MAXO+1] = { A(0,0,0), /* NULL */ A(1,1,0), /* RCAT */ A(1,0,0), /* ITEM */ A(1,0,0), /* SCALAR */ A(0,0,0), /* ITEM2 */ A(0,0,0), /* ITEM3 */ A(1,1,0), /* CONCAT */ A(3,1,0), /* REPEAT */ A(1,0,0), /* MATCH */ A(1,0,0), /* NMATCH */ A(1,0,0), /* SUBST */ A(1,0,0), /* NSUBST */ A(1,1,0), /* ASSIGN */ A(1,0,0), /* LOCAL */ A(3,3,0), /* AASSIGN */ A(0,0,0), /* SASSIGN */ A(3,0,0), /* CHOP */ A(1,0,0), /* DEFINED */ A(1,0,0), /* UNDEF */ A(1,0,0), /* STUDY */ A(1,1,0), /* POW */ A(1,1,0), /* MULTIPLY */ A(1,1,0), /* DIVIDE */ A(1,1,0), /* MODULO */ A(1,1,0), /* ADD */ A(1,1,0), /* SUBTRACT */ A(1,1,0), /* LEFT_SHIFT */ A(1,1,0), /* RIGHT_SHIFT */ A(1,1,0), /* LT */ A(1,1,0), /* GT */ A(1,1,0), /* LE */ A(1,1,0), /* GE */ A(1,1,0), /* EQ */ A(1,1,0), /* NE */ A(1,1,0), /* NCMP */ A(1,1,0), /* BIT_AND */ A(1,1,0), /* XOR */ A(1,1,0), /* BIT_OR */ A(1,0,0), /* AND */ A(1,0,0), /* OR */ A(1,0,0), /* COND_EXPR */ A(1,1,0), /* COMMA */ A(1,0,0), /* NEGATE */ A(1,0,0), /* NOT */ A(1,0,0), /* COMPLEMENT */ A(1,0,0), /* SELECT */ A(1,0,0), /* WRITE */ A(1,1,1), /* DBMOPEN */ A(1,0,0), /* DBMCLOSE */ A(1,1,0), /* OPEN */ A(1,0,0), /* TRANS */ A(1,0,0), /* NTRANS */ A(1,0,0), /* CLOSE */ A(0,0,0), /* EACH */ A(0,0,0), /* VALUES */ A(0,0,0), /* KEYS */ A(0,0,0), /* LARRAY */ A(0,0,0), /* ARRAY */ A(0,1,0), /* AELEM */ A(0,1,0), /* DELETE */ A(0,0,0), /* LHASH */ A(0,0,0), /* HASH */ A(0,1,0), /* HELEM */ A(0,1,0), /* LAELEM */ A(0,1,0), /* LHELEM */ A(0,3,3), /* LSLICE */ A(0,3,0), /* ASLICE */ A(0,3,0), /* HSLICE */ A(0,3,0), /* LASLICE */ A(0,3,0), /* LHSLICE */ A(0,3,1), /* SPLICE */ A(0,3,0), /* PUSH */ A(0,0,0), /* POP */ A(0,0,0), /* SHIFT */ A(1,1,0), /* UNPACK */ A(1,0,1), /* SPLIT */ A(1,0,0), /* LENGTH */ A(3,0,0), /* SPRINTF */ A(1,1,1), /* SUBSTR */ A(1,3,0), /* PACK */ A(0,3,0), /* GREP */ A(1,3,0), /* JOIN */ A(1,1,0), /* SLT */ A(1,1,0), /* SGT */ A(1,1,0), /* SLE */ A(1,1,0), /* SGE */ A(1,1,0), /* SEQ */ A(1,1,0), /* SNE */ A(1,1,0), /* SCMP */ A(0,3,0), /* SUBR */ A(0,3,0), /* DBSUBR */ A(1,0,0), /* CALLER */ A(1,3,0), /* SORT */ A(0,3,0), /* REVERSE */ A(0,3,0), /* WARN */ A(0,3,0), /* DIE */ A(1,3,0), /* PRINTF */ A(1,3,0), /* PRINT */ A(1,0,0), /* CHDIR */ A(1,0,0), /* EXIT */ A(1,0,0), /* RESET */ A(3,0,0), /* LIST */ A(1,0,0), /* EOF */ A(1,0,0), /* GETC */ A(1,0,0), /* TELL */ A5(1,1,1,1,0), /* RECV */ A(1,1,3), /* READ */ A(1,1,3), /* SYSREAD */ A(1,1,3), /* SYSWRITE */ A(1,1,3), /* SEND */ A(1,1,1), /* SEEK */ A(0,3,0), /* RETURN */ A(0,0,0), /* REDO */ A(0,0,0), /* NEXT */ A(0,0,0), /* LAST */ A(0,0,0), /* DUMP */ A(0,0,0), /* GOTO */ A(1,1,1), /* INDEX */ A(1,1,1), /* RINDEX */ A(0,0,0), /* TIME */ A(0,0,0), /* TIMES */ A(1,0,0), /* LOCALTIME */ A(1,0,0), /* GMTIME */ A(1,1,0), /* TRUNCATE */ A(1,0,0), /* LSTAT */ A(1,0,0), /* STAT */ A(1,1,0), /* CRYPT */ A(1,1,0), /* ATAN2 */ A(1,0,0), /* SIN */ A(1,0,0), /* COS */ A(1,0,0), /* RAND */ A(1,0,0), /* SRAND */ A(1,0,0), /* EXP */ A(1,0,0), /* LOG */ A(1,0,0), /* SQRT */ A(1,0,0), /* INT */ A(1,0,0), /* ORD */ A(1,0,0), /* ALARM */ A(1,0,0), /* SLEEP */ A(1,1,0), /* RANGE */ A(1,0,0), /* F_OR_R */ A(1,0,0), /* FLIP */ A(0,1,0), /* FLOP */ A(0,0,0), /* FORK */ A(0,0,0), /* WAIT */ A(1,1,0), /* WAITPID */ A(1,3,0), /* SYSTEM */ A(1,3,0), /* EXEC */ A(1,0,0), /* HEX */ A(1,0,0), /* OCT */ A(0,3,0), /* CHOWN */ A(0,3,0), /* KILL */ A(0,3,0), /* UNLINK */ A(0,3,0), /* CHMOD */ A(0,3,0), /* UTIME */ A(1,0,0), /* UMASK */ A(1,1,0), /* MSGGET */ A(1,1,1), /* SHMGET */ A(1,1,1), /* SEMGET */ A(1,1,1), /* MSGCTL */ A(1,1,1), /* SHMCTL */ A5(1,1,1,1,0), /* SEMCTL */ A(1,1,1), /* MSGSND */ A5(1,1,1,1,1), /* MSGRCV */ A(1,1,1), /* SEMOP */ A5(1,1,1,1,0), /* SHMREAD */ A5(1,1,1,1,0), /* SHMWRITE */ A(1,1,0), /* RENAME */ A(1,1,0), /* LINK */ A(1,1,0), /* MKDIR */ A(1,0,0), /* RMDIR */ A(0,0,0), /* GETPPID */ A(1,0,0), /* GETPGRP */ A(1,1,0), /* SETPGRP */ A(1,1,0), /* GETPRIORITY */ A(1,1,1), /* SETPRIORITY */ A(1,0,0), /* CHROOT */ A(1,1,1), /* FCNTL */ A(1,1,1), /* SYSIOCTL */ A(1,1,0), /* FLOCK */ A(0,3,0), /* UNSHIFT */ A(1,0,0), /* REQUIRE */ A(1,0,0), /* DOFILE */ A(1,0,0), /* EVAL */ A(1,0,0), /* FTRREAD */ A(1,0,0), /* FTRWRITE */ A(1,0,0), /* FTREXEC */ A(1,0,0), /* FTEREAD */ A(1,0,0), /* FTEWRITE */ A(1,0,0), /* FTEEXEC */ A(1,0,0), /* FTIS */ A(1,0,0), /* FTEOWNED */ A(1,0,0), /* FTROWNED */ A(1,0,0), /* FTZERO */ A(1,0,0), /* FTSIZE */ A(1,0,0), /* FTMTIME */ A(1,0,0), /* FTATIME */ A(1,0,0), /* FTCTIME */ A(1,0,0), /* FTSOCK */ A(1,0,0), /* FTCHR */ A(1,0,0), /* FTBLK */ A(1,0,0), /* FTFILE */ A(1,0,0), /* FTDIR */ A(1,0,0), /* FTPIPE */ A(1,0,0), /* FTLINK */ A(1,1,0), /* SYMLINK */ A(1,0,0), /* READLINK */ A(1,0,0), /* FTSUID */ A(1,0,0), /* FTSGID */ A(1,0,0), /* FTSVTX */ A(1,0,0), /* FTTTY */ A(1,0,0), /* FTTEXT */ A(1,0,0), /* FTBINARY */ A5(1,1,1,1,0), /* SOCKET */ A(1,1,0), /* BIND */ A(1,1,0), /* CONNECT */ A(1,1,0), /* LISTEN */ A(1,1,0), /* ACCEPT */ A(1,0,0), /* GHBYNAME */ A(1,1,0), /* GHBYADDR */ A(0,0,0), /* GHOSTENT */ A(1,0,0), /* GNBYNAME */ A(1,1,0), /* GNBYADDR */ A(0,0,0), /* GNETENT */ A(1,0,0), /* GPBYNAME */ A(1,0,0), /* GPBYNUMBER */ A(0,0,0), /* GPROTOENT */ A(1,1,0), /* GSBYNAME */ A(1,1,0), /* GSBYPORT */ A(0,0,0), /* GSERVENT */ A(1,0,0), /* SHOSTENT */ A(1,0,0), /* SNETENT */ A(1,0,0), /* SPROTOENT */ A(1,0,0), /* SSERVENT */ A(0,0,0), /* EHOSTENT */ A(0,0,0), /* ENETENT */ A(0,0,0), /* EPROTOENT */ A(0,0,0), /* ESERVENT */ A5(1,1,1,1,1), /* SOCKPAIR */ A(1,1,0), /* SHUTDOWN */ A(1,1,1), /* GSOCKOPT */ A5(1,1,1,1,0), /* SSOCKOPT */ A(1,0,0), /* GETSOCKNAME */ A(1,0,0), /* GETPEERNAME */ A5(1,1,1,1,0), /* SSELECT */ A(1,0,0), /* FILENO */ A(1,0,0), /* BINMODE */ A(1,1,1), /* VEC */ A(1,0,0), /* GPWNAM */ A(1,0,0), /* GPWUID */ A(0,0,0), /* GPWENT */ A(0,0,0), /* SPWENT */ A(0,0,0), /* EPWENT */ A(1,0,0), /* GGRNAM */ A(1,0,0), /* GGRGID */ A(0,0,0), /* GGRENT */ A(0,0,0), /* SGRENT */ A(0,0,0), /* EGRENT */ A(0,0,0), /* GETLOGIN */ A(1,1,0), /* OPENDIR */ A(1,0,0), /* READDIR */ A(1,0,0), /* TELLDIR */ A(1,1,0), /* SEEKDIR */ A(1,0,0), /* REWINDDIR */ A(1,0,0), /* CLOSEDIR */ A(1,3,0), /* SYSCALL */ A(1,1,0), /* PIPE */ A(0,0,0), /* TRY */ A(1,0,0), /* EVALONCE */ 0 }; #undef A #undef A5 #endif int do_trans(); int do_split(); bool do_eof(); long do_tell(); bool do_seek(); int do_tms(); int do_time(); int do_stat(); STR *do_push(); FILE *nextargv(); STR *do_fttext(); int do_slice(); Index: head/gnu/usr.bin/perl/perl/config.h =================================================================== --- head/gnu/usr.bin/perl/perl/config.h (revision 2652) +++ head/gnu/usr.bin/perl/perl/config.h (revision 2653) @@ -1,892 +1,769 @@ #ifndef config_h #define config_h /* config.h * This file was produced by running the config.h.SH script, which * gets its values from config.sh, which is generally produced by * running Configure. * * Feel free to modify any of this as the need arises. Note, however, * that running config.h.SH again will wipe out any changes you've made. * For a more permanent change edit config.sh and rerun config.h.SH. */ /*SUPPRESS 460*/ -/* EUNICE - * This symbol, if defined, indicates that the program is being compiled - * under the EUNICE package under VMS. The program will need to handle - * things like files that don't go away the first time you unlink them, - * due to version numbering. It will also need to compensate for lack - * of a respectable link() command. - */ -/* VMS - * This symbol, if defined, indicates that the program is running under - * VMS. It is currently only set in conjunction with the EUNICE symbol. - */ -/*#undef EUNICE /**/ -/*#undef VMS /**/ +/*#undef EUNICE */ +/*#undef VMS */ /* LOC_SED * This symbol holds the complete pathname to the sed program. */ #define LOC_SED "/usr/bin/sed" /**/ /* ALIGN_BYTES * This symbol contains the number of bytes required to align a double. * Usual values are 2, 4, and 8. */ #define ALIGN_BYTES 4 /**/ /* BIN * This symbol holds the name of the directory in which the user wants * to keep publicly executable images for the package in question. It * is most often a local directory such as /usr/local/bin. */ #define BIN "/usr/local/bin" /**/ /* BYTEORDER * This symbol contains an encoding of the order of bytes in a long. * Usual values (in hex) are 0x1234, 0x4321, 0x2143, 0x3412... */ #define BYTEORDER 0x1234 /**/ /* CPPSTDIN * This symbol contains the first part of the string which will invoke * the C preprocessor on the standard input and produce to standard * output. Typical value of "cc -E" or "/lib/cpp". */ /* CPPMINUS * This symbol contains the second part of the string which will invoke * the C preprocessor on the standard input and produce to standard * output. This symbol will have the value "-" if CPPSTDIN needs a minus * to specify standard input, otherwise the value is "". */ #define CPPSTDIN "cc -E" #define CPPMINUS "-" /* HAS_BCMP * This symbol, if defined, indicates that the bcmp routine is available * to compare blocks of memory. If undefined, use memcmp. If that's * not available, roll your own. */ #define HAS_BCMP /**/ /* HAS_BCOPY * This symbol, if defined, indicates that the bcopy routine is available * to copy blocks of memory. Otherwise you should probably use memcpy(). * If neither is defined, roll your own. */ /* SAFE_BCOPY * This symbol, if defined, indicates that the bcopy routine is available * to copy potentially overlapping copy blocks of bcopy. Otherwise you * should probably use memmove() or memcpy(). If neither is defined, * roll your own. */ #define HAS_BCOPY /**/ #define SAFE_BCOPY /**/ /* HAS_BZERO * This symbol, if defined, indicates that the bzero routine is available * to zero blocks of memory. Otherwise you should probably use memset() * or roll your own. */ #define HAS_BZERO /**/ /* CASTNEGFLOAT * This symbol, if defined, indicates that this C compiler knows how to * cast negative or large floating point numbers to unsigned longs, ints * and shorts. */ /* CASTFLAGS * This symbol contains flags that say what difficulties the compiler * has casting odd floating values to unsigned long: * 1 = couldn't cast < 0 * 2 = couldn't cast >= 0x80000000 */ #define CASTNEGFLOAT /**/ #define CASTFLAGS 0 /**/ /* CHARSPRINTF * This symbol is defined if this system declares "char *sprintf()" in * stdio.h. The trend seems to be to declare it as "int sprintf()". It * is up to the package author to declare sprintf correctly based on the * symbol. */ -/*#undef CHARSPRINTF /**/ +/*#undef CHARSPRINTF */ /* HAS_CHSIZE * This symbol, if defined, indicates that the chsize routine is available * to truncate files. You might need a -lx to get this routine. */ -/*#undef HAS_CHSIZE /**/ +/*#undef HAS_CHSIZE */ /* HAS_CRYPT * This symbol, if defined, indicates that the crypt routine is available * to encrypt passwords and the like. */ #define HAS_CRYPT /**/ /* CSH * This symbol, if defined, indicates that the C-shell exists. * If defined, contains the full pathname of csh. */ #define CSH "/bin/csh" /**/ /* DOSUID * This symbol, if defined, indicates that the C program should * check the script that it is executing for setuid/setgid bits, and * attempt to emulate setuid/setgid on systems that have disabled * setuid #! scripts because the kernel can't do it securely. * It is up to the package designer to make sure that this emulation * is done securely. Among other things, it should do an fstat on * the script it just opened to make sure it really is a setuid/setgid * script, it should make sure the arguments passed correspond exactly * to the argument on the #! line, and it should not trust any * subprocesses to which it must pass the filename rather than the * file descriptor of the script to be executed. */ -/*#undef DOSUID /**/ +/*#undef DOSUID */ /* HAS_DUP2 * This symbol, if defined, indicates that the dup2 routine is available * to dup file descriptors. Otherwise you should use dup(). */ #define HAS_DUP2 /**/ /* HAS_FCHMOD * This symbol, if defined, indicates that the fchmod routine is available * to change mode of opened files. If unavailable, use chmod(). */ #define HAS_FCHMOD /**/ /* HAS_FCHOWN * This symbol, if defined, indicates that the fchown routine is available * to change ownership of opened files. If unavailable, use chown(). */ #define HAS_FCHOWN /**/ /* HAS_FCNTL * This symbol, if defined, indicates to the C program that * the fcntl() function exists. */ #define HAS_FCNTL /**/ /* FLEXFILENAMES * This symbol, if defined, indicates that the system supports filenames * longer than 14 characters. */ #define FLEXFILENAMES /**/ /* HAS_FLOCK * This symbol, if defined, indicates that the flock() routine is * available to do file locking. */ #define HAS_FLOCK /**/ /* HAS_GETGROUPS * This symbol, if defined, indicates that the getgroups() routine is * available to get the list of process groups. If unavailable, multiple * groups are probably not supported. */ #define HAS_GETGROUPS /**/ /* HAS_GETHOSTENT * This symbol, if defined, indicates that the gethostent() routine is * available to lookup host names in some data base or other. */ -/*#undef HAS_GETHOSTENT /**/ +/*#undef HAS_GETHOSTENT */ /* HAS_GETPGRP * This symbol, if defined, indicates that the getpgrp() routine is * available to get the current process group. */ #define HAS_GETPGRP /**/ /* HAS_GETPGRP2 * This symbol, if defined, indicates that the getpgrp2() (as in DG/UX) * routine is available to get the current process group. */ -/*#undef HAS_GETPGRP2 /**/ +/*#undef HAS_GETPGRP2 */ /* HAS_GETPRIORITY * This symbol, if defined, indicates that the getpriority() routine is * available to get a process's priority. */ #define HAS_GETPRIORITY /**/ /* HAS_HTONS * This symbol, if defined, indicates that the htons routine (and friends) * are available to do network order byte swapping. */ /* HAS_HTONL * This symbol, if defined, indicates that the htonl routine (and friends) * are available to do network order byte swapping. */ /* HAS_NTOHS * This symbol, if defined, indicates that the ntohs routine (and friends) * are available to do network order byte swapping. */ /* HAS_NTOHL * This symbol, if defined, indicates that the ntohl routine (and friends) * are available to do network order byte swapping. */ #define HAS_HTONS /**/ #define HAS_HTONL /**/ #define HAS_NTOHS /**/ #define HAS_NTOHL /**/ /* index * This preprocessor symbol is defined, along with rindex, if the system * uses the strchr and strrchr routines instead. */ /* rindex * This preprocessor symbol is defined, along with index, if the system * uses the strchr and strrchr routines instead. */ -/*#undef index strchr /* cultural */ -/*#undef rindex strrchr /* differences? */ /* HAS_ISASCII * This symbol, if defined, indicates that the isascii routine is available * to test characters for asciiness. */ #define HAS_ISASCII /**/ /* HAS_KILLPG * This symbol, if defined, indicates that the killpg routine is available * to kill process groups. If unavailable, you probably should use kill * with a negative process number. */ #define HAS_KILLPG /**/ /* HAS_LSTAT * This symbol, if defined, indicates that the lstat() routine is * available to stat symbolic links. */ #define HAS_LSTAT /**/ /* HAS_MEMCMP * This symbol, if defined, indicates that the memcmp routine is available * to compare blocks of memory. If undefined, roll your own. */ #define HAS_MEMCMP /**/ /* HAS_MEMCPY * This symbol, if defined, indicates that the memcpy routine is available * to copy blocks of memory. Otherwise you should probably use bcopy(). * If neither is defined, roll your own. */ /* SAFE_MEMCPY * This symbol, if defined, indicates that the memcpy routine is available * to copy potentially overlapping copy blocks of memory. Otherwise you * should probably use memmove() or bcopy(). If neither is defined, * roll your own. */ #define HAS_MEMCPY /**/ #define SAFE_MEMCPY /**/ /* HAS_MEMMOVE * This symbol, if defined, indicates that the memmove routine is available * to move potentially overlapping blocks of memory. Otherwise you * should use bcopy() or roll your own. */ #define HAS_MEMMOVE /**/ /* HAS_MEMSET * This symbol, if defined, indicates that the memset routine is available * to set a block of memory to a character. If undefined, roll your own. */ #define HAS_MEMSET /**/ /* HAS_MKDIR * This symbol, if defined, indicates that the mkdir routine is available * to create directories. Otherwise you should fork off a new process to * exec /bin/mkdir. */ #define HAS_MKDIR /**/ -/* HAS_MSG - * This symbol, if defined, indicates that the entire msg*(2) library is - * supported. - */ -/*#undef HAS_MSG /**/ -/* HAS_MSGCTL - * This symbol, if defined, indicates that the msgctl() routine is - * available to control message passing. - */ -/*#undef HAS_MSGCTL /**/ - -/* HAS_MSGGET - * This symbol, if defined, indicates that the msgget() routine is - * available to get messages. - */ -/*#undef HAS_MSGGET /**/ - -/* HAS_MSGRCV - * This symbol, if defined, indicates that the msgrcv() routine is - * available to receive messages. - */ -/*#undef HAS_MSGRCV /**/ - -/* HAS_MSGSND - * This symbol, if defined, indicates that the msgsnd() routine is - * available to send messages. - */ -/*#undef HAS_MSGSND /**/ - /* HAS_NDBM * This symbol, if defined, indicates that ndbm.h exists and should * be included. */ #define HAS_NDBM /**/ /* HAS_ODBM * This symbol, if defined, indicates that dbm.h exists and should * be included. */ -/*#undef HAS_ODBM /**/ /* HAS_OPEN3 * This manifest constant lets the C program know that the three * argument form of open(2) is available. */ #define HAS_OPEN3 /**/ /* HAS_READDIR * This symbol, if defined, indicates that the readdir routine is available * from the C library to read directories. */ #define HAS_READDIR /**/ /* HAS_RENAME * This symbol, if defined, indicates that the rename routine is available * to rename files. Otherwise you should do the unlink(), link(), unlink() * trick. */ #define HAS_RENAME /**/ /* HAS_REWINDDIR * This symbol, if defined, indicates that the rewindir routine is * available to rewind directories. */ #define HAS_REWINDDIR /**/ /* HAS_RMDIR * This symbol, if defined, indicates that the rmdir routine is available * to remove directories. Otherwise you should fork off a new process to * exec /bin/rmdir. */ #define HAS_RMDIR /**/ /* HAS_SEEKDIR * This symbol, if defined, indicates that the seekdir routine is * available to seek into directories. */ #define HAS_SEEKDIR /**/ /* HAS_SELECT * This symbol, if defined, indicates that the select() subroutine * exists. */ #define HAS_SELECT /**/ -/* HAS_SEM - * This symbol, if defined, indicates that the entire sem*(2) library is - * supported. - */ -/*#undef HAS_SEM /**/ - -/* HAS_SEMCTL - * This symbol, if defined, indicates that the semctl() routine is - * available to control semaphores. - */ -/*#undef HAS_SEMCTL /**/ - -/* HAS_SEMGET - * This symbol, if defined, indicates that the semget() routine is - * available to get semaphores ids. - */ -/*#undef HAS_SEMGET /**/ - -/* HAS_SEMOP - * This symbol, if defined, indicates that the semop() routine is - * available to perform semaphore operations. - */ -/*#undef HAS_SEMOP /**/ - /* HAS_SETEGID * This symbol, if defined, indicates that the setegid routine is available * to change the effective gid of the current program. */ #define HAS_SETEGID /**/ /* HAS_SETEUID * This symbol, if defined, indicates that the seteuid routine is available * to change the effective uid of the current program. */ #define HAS_SETEUID /**/ /* HAS_SETPGRP * This symbol, if defined, indicates that the setpgrp() routine is * available to set the current process group. */ #define HAS_SETPGRP /**/ /* HAS_SETPGRP2 * This symbol, if defined, indicates that the setpgrp2() (as in DG/UX) * routine is available to set the current process group. */ -/*#undef HAS_SETPGRP2 /**/ /* HAS_SETPRIORITY * This symbol, if defined, indicates that the setpriority() routine is * available to set a process's priority. */ #define HAS_SETPRIORITY /**/ /* HAS_SETREGID * This symbol, if defined, indicates that the setregid routine is * available to change the real and effective gid of the current program. */ /* HAS_SETRESGID * This symbol, if defined, indicates that the setresgid routine is * available to change the real, effective and saved gid of the current * program. */ #define HAS_SETREGID /**/ -/*#undef HAS_SETRESGID /**/ /* HAS_SETREUID * This symbol, if defined, indicates that the setreuid routine is * available to change the real and effective uid of the current program. */ /* HAS_SETRESUID * This symbol, if defined, indicates that the setresuid routine is * available to change the real, effective and saved uid of the current * program. */ #define HAS_SETREUID /**/ -/*#undef HAS_SETRESUID /**/ /* HAS_SETRGID * This symbol, if defined, indicates that the setrgid routine is available * to change the real gid of the current program. */ #define HAS_SETRGID /**/ /* HAS_SETRUID * This symbol, if defined, indicates that the setruid routine is available * to change the real uid of the current program. */ #define HAS_SETRUID /**/ -/* HAS_SHM - * This symbol, if defined, indicates that the entire shm*(2) library is - * supported. - */ -/*#undef HAS_SHM /**/ -/* HAS_SHMAT - * This symbol, if defined, indicates that the shmat() routine is - * available to attach a shared memory segment. - */ -/* VOID_SHMAT - * This symbol, if defined, indicates that the shmat() routine - * returns a pointer of type void*. - */ -/*#undef HAS_SHMAT /**/ - -/*#undef VOIDSHMAT /**/ - -/* HAS_SHMCTL - * This symbol, if defined, indicates that the shmctl() routine is - * available to control a shared memory segment. - */ -/*#undef HAS_SHMCTL /**/ - -/* HAS_SHMDT - * This symbol, if defined, indicates that the shmdt() routine is - * available to detach a shared memory segment. - */ -/*#undef HAS_SHMDT /**/ - -/* HAS_SHMGET - * This symbol, if defined, indicates that the shmget() routine is - * available to get a shared memory segment id. - */ -/*#undef HAS_SHMGET /**/ - /* HAS_SOCKET * This symbol, if defined, indicates that the BSD socket interface is * supported. */ /* HAS_SOCKETPAIR * This symbol, if defined, indicates that the BSD socketpair call is * supported. */ /* OLDSOCKET * This symbol, if defined, indicates that the 4.1c BSD socket interface * is supported instead of the 4.2/4.3 BSD socket interface. */ #define HAS_SOCKET /**/ #define HAS_SOCKETPAIR /**/ -/*#undef OLDSOCKET /**/ /* STATBLOCKS * This symbol is defined if this system has a stat structure declaring * st_blksize and st_blocks. */ #define STATBLOCKS /**/ /* STDSTDIO * This symbol is defined if this system has a FILE structure declaring * _ptr and _cnt in stdio.h. */ -/*#undef STDSTDIO /**/ /* STRUCTCOPY * This symbol, if defined, indicates that this C compiler knows how * to copy structures. If undefined, you'll need to use a block copy * routine of some sort instead. */ #define STRUCTCOPY /**/ /* HAS_STRERROR * This symbol, if defined, indicates that the strerror() routine is * available to translate error numbers to strings. */ #define HAS_STRERROR /**/ /* HAS_SYMLINK * This symbol, if defined, indicates that the symlink routine is available * to create symbolic links. */ #define HAS_SYMLINK /**/ /* HAS_SYSCALL * This symbol, if defined, indicates that the syscall routine is available * to call arbitrary system calls. If undefined, that's tough. */ #define HAS_SYSCALL /**/ /* HAS_TELLDIR * This symbol, if defined, indicates that the telldir routine is * available to tell your location in directories. */ #define HAS_TELLDIR /**/ /* HAS_TRUNCATE * This symbol, if defined, indicates that the truncate routine is * available to truncate files. */ #define HAS_TRUNCATE /**/ /* HAS_VFORK * This symbol, if defined, indicates that vfork() exists. */ #define HAS_VFORK /**/ /* VOIDSIG * This symbol is defined if this system declares "void (*signal())()" in * signal.h. The old way was to declare it as "int (*signal())()". It * is up to the package author to declare things correctly based on the * symbol. */ /* TO_SIGNAL * This symbol's value is either "void" or "int", corresponding to the * appropriate return "type" of a signal handler. Thus, one can declare * a signal handler using "TO_SIGNAL (*handler())()", and define the * handler using "TO_SIGNAL handler(sig)". */ #define VOIDSIG /**/ #define TO_SIGNAL int /**/ /* HASVOLATILE * This symbol, if defined, indicates that this C compiler knows about * the volatile declaration. */ #define HASVOLATILE /**/ /* HAS_VPRINTF * This symbol, if defined, indicates that the vprintf routine is available * to printf with a pointer to an argument list. If unavailable, you * may need to write your own, probably in terms of _doprnt(). */ /* CHARVSPRINTF * This symbol is defined if this system has vsprintf() returning type * (char*). The trend seems to be to declare it as "int vsprintf()". It * is up to the package author to declare vsprintf correctly based on the * symbol. */ #define HAS_VPRINTF /**/ -/*#undef CHARVSPRINTF /**/ /* HAS_WAIT4 * This symbol, if defined, indicates that wait4() exists. */ #define HAS_WAIT4 /**/ /* HAS_WAITPID * This symbol, if defined, indicates that waitpid() exists. */ #define HAS_WAITPID /**/ /* GIDTYPE * This symbol has a value like gid_t, int, ushort, or whatever type is * used to declare group ids in the kernel. */ #define GIDTYPE gid_t /**/ /* GROUPSTYPE * This symbol has a value like gid_t, int, ushort, or whatever type is * used in the return value of getgroups(). */ -#define GROUPSTYPE int /**/ +#define GROUPSTYPE gid_t /**/ /* I_FCNTL * This manifest constant tells the C program to include . */ -/*#undef I_FCNTL /**/ /* I_GDBM * This symbol, if defined, indicates that gdbm.h exists and should * be included. */ -/*#undef I_GDBM /**/ /* I_GRP * This symbol, if defined, indicates to the C program that it should * include grp.h. */ #define I_GRP /**/ /* I_NETINET_IN * This symbol, if defined, indicates to the C program that it should * include netinet/in.h. */ /* I_SYS_IN * This symbol, if defined, indicates to the C program that it should * include sys/in.h. */ #define I_NETINET_IN /**/ -/*#undef I_SYS_IN /**/ /* I_PWD * This symbol, if defined, indicates to the C program that it should * include pwd.h. */ /* PWQUOTA * This symbol, if defined, indicates to the C program that struct passwd * contains pw_quota. */ /* PWAGE * This symbol, if defined, indicates to the C program that struct passwd * contains pw_age. */ /* PWCHANGE * This symbol, if defined, indicates to the C program that struct passwd * contains pw_change. */ /* PWCLASS * This symbol, if defined, indicates to the C program that struct passwd * contains pw_class. */ /* PWEXPIRE * This symbol, if defined, indicates to the C program that struct passwd * contains pw_expire. */ /* PWCOMMENT * This symbol, if defined, indicates to the C program that struct passwd * contains pw_comment. */ #define I_PWD /**/ -/*#undef PWQUOTA /**/ -/*#undef PWAGE /**/ #define PWCHANGE /**/ #define PWCLASS /**/ #define PWEXPIRE /**/ -/*#undef PWCOMMENT /**/ /* I_SYS_FILE * This manifest constant tells the C program to include . */ #define I_SYS_FILE /**/ /* I_SYSIOCTL * This symbol, if defined, indicates that sys/ioctl.h exists and should * be included. */ #define I_SYSIOCTL /**/ /* I_TIME * This symbol is defined if the program should include . */ /* I_SYS_TIME * This symbol is defined if the program should include . */ /* SYSTIMEKERNEL * This symbol is defined if the program should include * with KERNEL defined. */ /* I_SYS_SELECT * This symbol is defined if the program should include . */ -/*#undef I_TIME /**/ #define I_SYS_TIME /**/ -/*#undef SYSTIMEKERNEL /**/ -/*#undef I_SYS_SELECT /**/ /* I_UTIME * This symbol, if defined, indicates to the C program that it should * include utime.h. */ #define I_UTIME /**/ /* I_VARARGS * This symbol, if defined, indicates to the C program that it should * include varargs.h. */ #define I_VARARGS /**/ /* I_VFORK * This symbol, if defined, indicates to the C program that it should * include vfork.h. */ -/*#undef I_VFORK /**/ /* INTSIZE * This symbol contains the size of an int, so that the C preprocessor * can make decisions based on it. */ #define INTSIZE 4 /**/ /* I_DIRENT * This symbol, if defined, indicates that the program should use the * P1003-style directory routines, and include . */ /* I_SYS_DIR * This symbol, if defined, indicates that the program should use the * directory functions by including . */ /* I_NDIR * This symbol, if defined, indicates that the program should include the * system's version of ndir.h, rather than the one with this package. */ /* I_SYS_NDIR * This symbol, if defined, indicates that the program should include the * system's version of sys/ndir.h, rather than the one with this package. */ /* I_MY_DIR * This symbol, if defined, indicates that the program should compile * the ndir.c code provided with the package. */ /* DIRNAMLEN * This symbol, if defined, indicates to the C program that the length * of directory entry names is provided by a d_namlen field. Otherwise * you need to do strlen() on the d_name field. */ #define I_DIRENT /**/ -/*#undef I_SYS_DIR /**/ -/*#undef I_NDIR /**/ -/*#undef I_SYS_NDIR /**/ -/*#undef I_MY_DIR /**/ -/*#undef DIRNAMLEN /**/ /* MYMALLOC * This symbol, if defined, indicates that we're using our own malloc. */ /* MALLOCPTRTYPE * This symbol defines the kind of ptr returned by malloc and realloc. */ #define MYMALLOC /**/ #define MALLOCPTRTYPE void /**/ /* RANDBITS * This symbol contains the number of bits of random number the rand() * function produces. Usual values are 15, 16, and 31. */ #define RANDBITS 31 /**/ /* SCRIPTDIR * This symbol holds the name of the directory in which the user wants * to keep publicly executable scripts for the package in question. It * is often a directory that is mounted across diverse architectures. */ #define SCRIPTDIR "/usr/local/bin" /**/ /* SIG_NAME * This symbol contains an list of signal names in order. */ #define SIG_NAME "ZERO","HUP","INT","QUIT","ILL","TRAP","ABRT","EMT","FPE","KILL","BUS","SEGV","SYS","PIPE","ALRM","TERM","URG","STOP","TSTP","CONT","CHLD","TTIN","TTOU","IO","XCPU","XFSZ","VTALRM","PROF","WINCH","INFO","USR1","USR2" /**/ /* STDCHAR * This symbol is defined to be the type of char used in stdio.h. * It has the values "unsigned char" or "char". */ #define STDCHAR char /**/ /* UIDTYPE * This symbol has a value like uid_t, int, ushort, or whatever type is * used to declare user ids in the kernel. */ #define UIDTYPE uid_t /**/ /* VOIDHAVE * This symbol indicates how much support of the void type is given by this * compiler. What various bits mean: * * 1 = supports declaration of void * 2 = supports arrays of pointers to functions returning void * 4 = supports comparisons between pointers to void functions and * addresses of void functions * * The package designer should define VOIDWANT to indicate the requirements * of the package. This can be done either by #defining VOIDWANT before * including config.h, or by defining voidwant in Myinit.U. If the level * of void support necessary is not present, config.h defines void to "int", * VOID to the empty string, and VOIDP to "char *". */ /* void * This symbol is used for void casts. On implementations which support * void appropriately, its value is "void". Otherwise, its value maps * to "int". */ /* VOID * This symbol's value is "void" if the implementation supports void * appropriately. Otherwise, its value is the empty string. The primary * use of this symbol is in specifying void parameter lists for function * prototypes. */ /* VOIDP * This symbol is used for casting generic pointers. On implementations * which support void appropriately, its value is "void *". Otherwise, * its value is "char *". */ #ifndef VOIDWANT #define VOIDWANT 7 #endif #define VOIDHAVE 7 #if (VOIDHAVE & VOIDWANT) != VOIDWANT #define void int /* is void to be avoided? */ #define VOID #define VOIDP (char *) #define M_VOID /* Xenix strikes again */ #else #define VOID void #define VOIDP (void *) #endif /* PRIVLIB * This symbol contains the name of the private library for this package. * The library is private in the sense that it needn't be in anyone's * execution path, but it should be accessible by the world. The program * should be prepared to do ~ expansion. */ #define PRIVLIB "/usr/local/lib/perl" /**/ #endif Index: head/gnu/usr.bin/perl/perl/consarg.c =================================================================== --- head/gnu/usr.bin/perl/perl/consarg.c (revision 2652) +++ head/gnu/usr.bin/perl/perl/consarg.c (revision 2653) @@ -1,1292 +1,1295 @@ -/* $RCSfile: consarg.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:35 $ +/* $RCSfile: consarg.c,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:32 $ * * Copyright (c) 1991, Larry Wall * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. * * $Log: consarg.c,v $ + * Revision 1.1.1.1 1994/09/10 06:27:32 gclarkii + * Initial import of Perl 4.046 bmaked + * * Revision 1.1.1.1 1993/08/23 21:29:35 nate * PERL! * * Revision 4.0.1.4 92/06/08 12:26:27 lwall * patch20: new warning for use of x with non-numeric right operand * patch20: modulus with highest bit in left operand set didn't always work * patch20: illegal lvalue message could be followed by core dump * patch20: deleted some minor memory leaks * * Revision 4.0.1.3 91/11/05 16:21:16 lwall * patch11: random cleanup * patch11: added eval {} * patch11: added sort {} LIST * patch11: "foo" x -1 dumped core * patch11: substr() and vec() weren't allowed in an lvalue list * * Revision 4.0.1.2 91/06/07 10:33:12 lwall * patch4: new copyright notice * patch4: length($`), length($&), length($') now optimized to avoid string copy * * Revision 4.0.1.1 91/04/11 17:38:34 lwall * patch1: fixed "Bad free" error * * Revision 4.0 91/03/20 01:06:15 lwall * 4.0 baseline. * */ #include "EXTERN.h" #include "perl.h" static int nothing_in_common(); static int arg_common(); static int spat_common(); ARG * make_split(stab,arg,limarg) register STAB *stab; register ARG *arg; ARG *limarg; { register SPAT *spat; if (arg->arg_type != O_MATCH) { Newz(201,spat,1,SPAT); spat->spat_next = curstash->tbl_spatroot; /* link into spat list */ curstash->tbl_spatroot = spat; spat->spat_runtime = arg; arg = make_match(O_MATCH,stab2arg(A_STAB,defstab),spat); } Renew(arg,4,ARG); arg->arg_len = 3; if (limarg) { if (limarg->arg_type == O_ITEM) { Copy(limarg+1,arg+3,1,ARG); limarg[1].arg_type = A_NULL; arg_free(limarg); } else { arg[3].arg_flags = 0; arg[3].arg_len = 0; arg[3].arg_type = A_EXPR; arg[3].arg_ptr.arg_arg = limarg; } } else { arg[3].arg_flags = 0; arg[3].arg_len = 0; arg[3].arg_type = A_NULL; arg[3].arg_ptr.arg_arg = Nullarg; } arg->arg_type = O_SPLIT; spat = arg[2].arg_ptr.arg_spat; spat->spat_repl = stab2arg(A_STAB,aadd(stab)); if (spat->spat_short) { /* exact match can bypass regexec() */ if (!((spat->spat_flags & SPAT_SCANFIRST) && (spat->spat_flags & SPAT_ALL) )) { str_free(spat->spat_short); spat->spat_short = Nullstr; } } return arg; } ARG * mod_match(type,left,pat) register ARG *left; register ARG *pat; { register SPAT *spat; register ARG *newarg; if (!pat) return Nullarg; if ((pat->arg_type == O_MATCH || pat->arg_type == O_SUBST || pat->arg_type == O_TRANS || pat->arg_type == O_SPLIT ) && pat[1].arg_ptr.arg_stab == defstab ) { switch (pat->arg_type) { case O_MATCH: newarg = make_op(type == O_MATCH ? O_MATCH : O_NMATCH, pat->arg_len, left,Nullarg,Nullarg); break; case O_SUBST: newarg = l(make_op(type == O_MATCH ? O_SUBST : O_NSUBST, pat->arg_len, left,Nullarg,Nullarg)); break; case O_TRANS: newarg = l(make_op(type == O_MATCH ? O_TRANS : O_NTRANS, pat->arg_len, left,Nullarg,Nullarg)); break; case O_SPLIT: newarg = make_op(type == O_MATCH ? O_SPLIT : O_SPLIT, pat->arg_len, left,Nullarg,Nullarg); break; } if (pat->arg_len >= 2) { newarg[2].arg_type = pat[2].arg_type; newarg[2].arg_ptr = pat[2].arg_ptr; newarg[2].arg_len = pat[2].arg_len; newarg[2].arg_flags = pat[2].arg_flags; if (pat->arg_len >= 3) { newarg[3].arg_type = pat[3].arg_type; newarg[3].arg_ptr = pat[3].arg_ptr; newarg[3].arg_len = pat[3].arg_len; newarg[3].arg_flags = pat[3].arg_flags; } } free_arg(pat); } else { Newz(202,spat,1,SPAT); spat->spat_next = curstash->tbl_spatroot; /* link into spat list */ curstash->tbl_spatroot = spat; spat->spat_runtime = pat; newarg = make_op(type,2,left,Nullarg,Nullarg); newarg[2].arg_type = A_SPAT | A_DONT; newarg[2].arg_ptr.arg_spat = spat; } return newarg; } ARG * make_op(type,newlen,arg1,arg2,arg3) int type; int newlen; ARG *arg1; ARG *arg2; ARG *arg3; { register ARG *arg; register ARG *chld; register unsigned doarg; register int i; extern ARG *arg4; /* should be normal arguments, really */ extern ARG *arg5; arg = op_new(newlen); arg->arg_type = type; /*SUPPRESS 560*/ if (chld = arg1) { if (chld->arg_type == O_ITEM && (hoistable[ i = (chld[1].arg_type&A_MASK)] || i == A_LVAL || (i == A_LEXPR && (chld[1].arg_ptr.arg_arg->arg_type == O_LIST || chld[1].arg_ptr.arg_arg->arg_type == O_ARRAY || chld[1].arg_ptr.arg_arg->arg_type == O_HASH )))) { arg[1].arg_type = chld[1].arg_type; arg[1].arg_ptr = chld[1].arg_ptr; arg[1].arg_flags |= chld[1].arg_flags; arg[1].arg_len = chld[1].arg_len; free_arg(chld); } else { arg[1].arg_type = A_EXPR; arg[1].arg_ptr.arg_arg = chld; } } /*SUPPRESS 560*/ if (chld = arg2) { if (chld->arg_type == O_ITEM && (hoistable[chld[1].arg_type&A_MASK] || (type == O_ASSIGN && ((chld[1].arg_type == A_READ && !(arg[1].arg_type & A_DONT)) || (chld[1].arg_type == A_INDREAD && !(arg[1].arg_type & A_DONT)) || (chld[1].arg_type == A_GLOB && !(arg[1].arg_type & A_DONT)) ) ) ) ) { arg[2].arg_type = chld[1].arg_type; arg[2].arg_ptr = chld[1].arg_ptr; arg[2].arg_len = chld[1].arg_len; free_arg(chld); } else { arg[2].arg_type = A_EXPR; arg[2].arg_ptr.arg_arg = chld; } } /*SUPPRESS 560*/ if (chld = arg3) { if (chld->arg_type == O_ITEM && hoistable[chld[1].arg_type&A_MASK]) { arg[3].arg_type = chld[1].arg_type; arg[3].arg_ptr = chld[1].arg_ptr; arg[3].arg_len = chld[1].arg_len; free_arg(chld); } else { arg[3].arg_type = A_EXPR; arg[3].arg_ptr.arg_arg = chld; } } if (newlen >= 4 && (chld = arg4)) { if (chld->arg_type == O_ITEM && hoistable[chld[1].arg_type&A_MASK]) { arg[4].arg_type = chld[1].arg_type; arg[4].arg_ptr = chld[1].arg_ptr; arg[4].arg_len = chld[1].arg_len; free_arg(chld); } else { arg[4].arg_type = A_EXPR; arg[4].arg_ptr.arg_arg = chld; } } if (newlen >= 5 && (chld = arg5)) { if (chld->arg_type == O_ITEM && hoistable[chld[1].arg_type&A_MASK]) { arg[5].arg_type = chld[1].arg_type; arg[5].arg_ptr = chld[1].arg_ptr; arg[5].arg_len = chld[1].arg_len; free_arg(chld); } else { arg[5].arg_type = A_EXPR; arg[5].arg_ptr.arg_arg = chld; } } doarg = opargs[type]; for (i = 1; i <= newlen; ++i) { if (!(doarg & 1)) arg[i].arg_type |= A_DONT; if (doarg & 2) arg[i].arg_flags |= AF_ARYOK; doarg >>= 2; } #ifdef DEBUGGING if (debug & 16) { fprintf(stderr,"%lx <= make_op(%s",arg,opname[arg->arg_type]); if (arg1) fprintf(stderr,",%s=%lx", argname[arg[1].arg_type&A_MASK],arg[1].arg_ptr.arg_arg); if (arg2) fprintf(stderr,",%s=%lx", argname[arg[2].arg_type&A_MASK],arg[2].arg_ptr.arg_arg); if (arg3) fprintf(stderr,",%s=%lx", argname[arg[3].arg_type&A_MASK],arg[3].arg_ptr.arg_arg); if (newlen >= 4) fprintf(stderr,",%s=%lx", argname[arg[4].arg_type&A_MASK],arg[4].arg_ptr.arg_arg); if (newlen >= 5) fprintf(stderr,",%s=%lx", argname[arg[5].arg_type&A_MASK],arg[5].arg_ptr.arg_arg); fprintf(stderr,")\n"); } #endif arg = evalstatic(arg); /* see if we can consolidate anything */ return arg; } ARG * evalstatic(arg) register ARG *arg; { static STR *str = Nullstr; register STR *s1; register STR *s2; double value; /* must not be register */ register char *tmps; int i; unsigned long tmplong; long tmp2; double exp(), log(), sqrt(), modf(); char *crypt(); double sin(), cos(), atan2(), pow(); if (!arg || !arg->arg_len) return arg; if (!str) str = Str_new(20,0); if (arg[1].arg_type == A_SINGLE) s1 = arg[1].arg_ptr.arg_str; else s1 = Nullstr; if (arg->arg_len >= 2 && arg[2].arg_type == A_SINGLE) s2 = arg[2].arg_ptr.arg_str; else s2 = Nullstr; #define CHECK1 if (!s1) return arg #define CHECK2 if (!s2) return arg #define CHECK12 if (!s1 || !s2) return arg switch (arg->arg_type) { default: return arg; case O_SORT: if (arg[1].arg_type == A_CMD) arg[1].arg_type |= A_DONT; return arg; case O_EVAL: if (arg[1].arg_type == A_CMD) { arg->arg_type = O_TRY; arg[1].arg_type |= A_DONT; return arg; } CHECK1; arg->arg_type = O_EVALONCE; return arg; case O_AELEM: CHECK2; i = (int)str_gnum(s2); if (i < 32767 && i >= 0) { arg->arg_type = O_ITEM; arg->arg_len = 1; arg[1].arg_type = A_ARYSTAB; /* $abc[123] is hoistable now */ arg[1].arg_len = i; str_free(s2); Renew(arg, 2, ARG); } return arg; case O_CONCAT: CHECK12; str_sset(str,s1); str_scat(str,s2); break; case O_REPEAT: CHECK2; if (dowarn && !s2->str_nok && !looks_like_number(s2)) warn("Right operand of x is not numeric"); CHECK1; i = (int)str_gnum(s2); tmps = str_get(s1); str_nset(str,"",0); if (i > 0) { STR_GROW(str, i * s1->str_cur + 1); repeatcpy(str->str_ptr, tmps, s1->str_cur, i); str->str_cur = i * s1->str_cur; str->str_ptr[str->str_cur] = '\0'; } break; case O_MULTIPLY: CHECK12; value = str_gnum(s1); str_numset(str,value * str_gnum(s2)); break; case O_DIVIDE: CHECK12; value = str_gnum(s2); if (value == 0.0) yyerror("Illegal division by constant zero"); else #ifdef SLOPPYDIVIDE /* insure that 20./5. == 4. */ { double x; int k; x = str_gnum(s1); if ((double)(int)x == x && (double)(int)value == value && (k = (int)x/(int)value)*(int)value == (int)x) { value = k; } else { value = x/value; } str_numset(str,value); } #else str_numset(str,str_gnum(s1) / value); #endif break; case O_MODULO: CHECK12; tmplong = (unsigned long)str_gnum(s2); if (tmplong == 0L) { yyerror("Illegal modulus of constant zero"); return arg; } value = str_gnum(s1); #ifndef lint if (value >= 0.0) str_numset(str,(double)(((unsigned long)value) % tmplong)); else { tmp2 = (long)value; str_numset(str,(double)((tmplong-((-tmp2 - 1) % tmplong)) - 1)); } #else tmp2 = tmp2; #endif break; case O_ADD: CHECK12; value = str_gnum(s1); str_numset(str,value + str_gnum(s2)); break; case O_SUBTRACT: CHECK12; value = str_gnum(s1); str_numset(str,value - str_gnum(s2)); break; case O_LEFT_SHIFT: CHECK12; value = str_gnum(s1); i = (int)str_gnum(s2); #ifndef lint str_numset(str,(double)(((long)value) << i)); #endif break; case O_RIGHT_SHIFT: CHECK12; value = str_gnum(s1); i = (int)str_gnum(s2); #ifndef lint str_numset(str,(double)(((long)value) >> i)); #endif break; case O_LT: CHECK12; value = str_gnum(s1); str_numset(str,(value < str_gnum(s2)) ? 1.0 : 0.0); break; case O_GT: CHECK12; value = str_gnum(s1); str_numset(str,(value > str_gnum(s2)) ? 1.0 : 0.0); break; case O_LE: CHECK12; value = str_gnum(s1); str_numset(str,(value <= str_gnum(s2)) ? 1.0 : 0.0); break; case O_GE: CHECK12; value = str_gnum(s1); str_numset(str,(value >= str_gnum(s2)) ? 1.0 : 0.0); break; case O_EQ: CHECK12; if (dowarn) { if ((!s1->str_nok && !looks_like_number(s1)) || (!s2->str_nok && !looks_like_number(s2)) ) warn("Possible use of == on string value"); } value = str_gnum(s1); str_numset(str,(value == str_gnum(s2)) ? 1.0 : 0.0); break; case O_NE: CHECK12; value = str_gnum(s1); str_numset(str,(value != str_gnum(s2)) ? 1.0 : 0.0); break; case O_NCMP: CHECK12; value = str_gnum(s1); value -= str_gnum(s2); if (value > 0.0) value = 1.0; else if (value < 0.0) value = -1.0; str_numset(str,value); break; case O_BIT_AND: CHECK12; value = str_gnum(s1); #ifndef lint str_numset(str,(double)(U_L(value) & U_L(str_gnum(s2)))); #endif break; case O_XOR: CHECK12; value = str_gnum(s1); #ifndef lint str_numset(str,(double)(U_L(value) ^ U_L(str_gnum(s2)))); #endif break; case O_BIT_OR: CHECK12; value = str_gnum(s1); #ifndef lint str_numset(str,(double)(U_L(value) | U_L(str_gnum(s2)))); #endif break; case O_AND: CHECK12; if (str_true(s1)) str_sset(str,s2); else str_sset(str,s1); break; case O_OR: CHECK12; if (str_true(s1)) str_sset(str,s1); else str_sset(str,s2); break; case O_COND_EXPR: CHECK12; if ((arg[3].arg_type & A_MASK) != A_SINGLE) return arg; if (str_true(s1)) str_sset(str,s2); else str_sset(str,arg[3].arg_ptr.arg_str); str_free(arg[3].arg_ptr.arg_str); Renew(arg, 3, ARG); break; case O_NEGATE: CHECK1; str_numset(str,(double)(-str_gnum(s1))); break; case O_NOT: CHECK1; #ifdef NOTNOT { char xxx = str_true(s1); str_numset(str,(double)!xxx); } #else str_numset(str,(double)(!str_true(s1))); #endif break; case O_COMPLEMENT: CHECK1; #ifndef lint str_numset(str,(double)(~U_L(str_gnum(s1)))); #endif break; case O_SIN: CHECK1; str_numset(str,sin(str_gnum(s1))); break; case O_COS: CHECK1; str_numset(str,cos(str_gnum(s1))); break; case O_ATAN2: CHECK12; value = str_gnum(s1); str_numset(str,atan2(value, str_gnum(s2))); break; case O_POW: CHECK12; value = str_gnum(s1); str_numset(str,pow(value, str_gnum(s2))); break; case O_LENGTH: if (arg[1].arg_type == A_STAB) { arg->arg_type = O_ITEM; arg[1].arg_type = A_LENSTAB; return arg; } CHECK1; str_numset(str, (double)str_len(s1)); break; case O_SLT: CHECK12; str_numset(str,(double)(str_cmp(s1,s2) < 0)); break; case O_SGT: CHECK12; str_numset(str,(double)(str_cmp(s1,s2) > 0)); break; case O_SLE: CHECK12; str_numset(str,(double)(str_cmp(s1,s2) <= 0)); break; case O_SGE: CHECK12; str_numset(str,(double)(str_cmp(s1,s2) >= 0)); break; case O_SEQ: CHECK12; str_numset(str,(double)(str_eq(s1,s2))); break; case O_SNE: CHECK12; str_numset(str,(double)(!str_eq(s1,s2))); break; case O_SCMP: CHECK12; str_numset(str,(double)(str_cmp(s1,s2))); break; case O_CRYPT: CHECK12; #ifdef HAS_CRYPT tmps = str_get(s1); str_set(str,crypt(tmps,str_get(s2))); #else yyerror( "The crypt() function is unimplemented due to excessive paranoia."); #endif break; case O_EXP: CHECK1; str_numset(str,exp(str_gnum(s1))); break; case O_LOG: CHECK1; str_numset(str,log(str_gnum(s1))); break; case O_SQRT: CHECK1; str_numset(str,sqrt(str_gnum(s1))); break; case O_INT: CHECK1; value = str_gnum(s1); if (value >= 0.0) (void)modf(value,&value); else { (void)modf(-value,&value); value = -value; } str_numset(str,value); break; case O_ORD: CHECK1; #ifndef I286 str_numset(str,(double)(*str_get(s1))); #else { int zapc; char *zaps; zaps = str_get(s1); zapc = (int) *zaps; str_numset(str,(double)(zapc)); } #endif break; } arg->arg_type = O_ITEM; /* note arg1 type is already SINGLE */ str_free(s1); arg[1].arg_ptr.arg_str = str; if (s2) { str_free(s2); arg[2].arg_ptr.arg_str = Nullstr; arg[2].arg_type = A_NULL; } str = Nullstr; return arg; } ARG * l(arg) register ARG *arg; { register int i; register ARG *arg1; register ARG *arg2; SPAT *spat; int arghog = 0; i = arg[1].arg_type & A_MASK; arg->arg_flags |= AF_COMMON; /* assume something in common */ /* which forces us to copy things */ if (i == A_ARYLEN) { arg[1].arg_type = A_LARYLEN; return arg; } if (i == A_ARYSTAB) { arg[1].arg_type = A_LARYSTAB; return arg; } /* see if it's an array reference */ if (i == A_EXPR || i == A_LEXPR) { arg1 = arg[1].arg_ptr.arg_arg; if (arg1->arg_type == O_LIST || arg1->arg_type == O_ITEM) { /* assign to list */ if (arg->arg_len > 1) { dehoist(arg,2); arg2 = arg[2].arg_ptr.arg_arg; if (nothing_in_common(arg1,arg2)) arg->arg_flags &= ~AF_COMMON; if (arg->arg_type == O_ASSIGN) { - if (arg1->arg_flags & AF_LOCAL) - arg->arg_flags |= AF_LOCAL; + if (arg1->arg_flags & AF_LOCAL_XX) + arg->arg_flags |= AF_LOCAL_XX; arg[1].arg_flags |= AF_ARYOK; arg[2].arg_flags |= AF_ARYOK; } } else if (arg->arg_type != O_CHOP) arg->arg_type = O_ASSIGN; /* possible local(); */ for (i = arg1->arg_len; i >= 1; i--) { switch (arg1[i].arg_type) { case A_STAR: case A_LSTAR: arg1[i].arg_type = A_LSTAR; break; case A_STAB: case A_LVAL: arg1[i].arg_type = A_LVAL; break; case A_ARYLEN: case A_LARYLEN: arg1[i].arg_type = A_LARYLEN; break; case A_ARYSTAB: case A_LARYSTAB: arg1[i].arg_type = A_LARYSTAB; break; case A_EXPR: case A_LEXPR: arg1[i].arg_type = A_LEXPR; switch(arg1[i].arg_ptr.arg_arg->arg_type) { case O_ARRAY: case O_LARRAY: arg1[i].arg_ptr.arg_arg->arg_type = O_LARRAY; arghog = 1; break; case O_AELEM: case O_LAELEM: arg1[i].arg_ptr.arg_arg->arg_type = O_LAELEM; break; case O_HASH: case O_LHASH: arg1[i].arg_ptr.arg_arg->arg_type = O_LHASH; arghog = 1; break; case O_HELEM: case O_LHELEM: arg1[i].arg_ptr.arg_arg->arg_type = O_LHELEM; break; case O_ASLICE: case O_LASLICE: arg1[i].arg_ptr.arg_arg->arg_type = O_LASLICE; break; case O_HSLICE: case O_LHSLICE: arg1[i].arg_ptr.arg_arg->arg_type = O_LHSLICE; break; case O_SUBSTR: case O_VEC: (void)l(arg1[i].arg_ptr.arg_arg); Renewc(arg1[i].arg_ptr.arg_arg->arg_ptr.arg_str, 1, struct lstring, STR); /* grow string struct to hold an lstring struct */ break; default: goto ill_item; } break; default: ill_item: (void)sprintf(tokenbuf, "Illegal item (%s) as lvalue", argname[arg1[i].arg_type&A_MASK]); yyerror(tokenbuf); } } if (arg->arg_len > 1) { if (arg2->arg_type == O_SPLIT && !arg2[3].arg_type && !arghog) { arg2[3].arg_type = A_SINGLE; arg2[3].arg_ptr.arg_str = str_nmake((double)arg1->arg_len + 1); /* limit split len*/ } } } else if (arg1->arg_type == O_AELEM || arg1->arg_type == O_LAELEM) if (arg->arg_type == O_DEFINED) arg1->arg_type = O_AELEM; else arg1->arg_type = O_LAELEM; else if (arg1->arg_type == O_ARRAY || arg1->arg_type == O_LARRAY) { arg1->arg_type = O_LARRAY; if (arg->arg_len > 1) { dehoist(arg,2); arg2 = arg[2].arg_ptr.arg_arg; if (arg2->arg_type == O_SPLIT) { /* use split's builtin =?*/ spat = arg2[2].arg_ptr.arg_spat; if (!(spat->spat_flags & SPAT_ONCE) && nothing_in_common(arg1,spat->spat_repl)) { spat->spat_repl[1].arg_ptr.arg_stab = arg1[1].arg_ptr.arg_stab; arg1[1].arg_ptr.arg_stab = Nullstab; spat->spat_flags |= SPAT_ONCE; arg_free(arg1); /* recursive */ arg[1].arg_ptr.arg_arg = Nullarg; free_arg(arg); /* non-recursive */ return arg2; /* split has builtin assign */ } } else if (nothing_in_common(arg1,arg2)) arg->arg_flags &= ~AF_COMMON; if (arg->arg_type == O_ASSIGN) { arg[1].arg_flags |= AF_ARYOK; arg[2].arg_flags |= AF_ARYOK; } } else if (arg->arg_type == O_ASSIGN) arg[1].arg_flags |= AF_ARYOK; } else if (arg1->arg_type == O_HELEM || arg1->arg_type == O_LHELEM) if (arg->arg_type == O_DEFINED) arg1->arg_type = O_HELEM; /* avoid creating one */ else arg1->arg_type = O_LHELEM; else if (arg1->arg_type == O_HASH || arg1->arg_type == O_LHASH) { arg1->arg_type = O_LHASH; if (arg->arg_len > 1) { dehoist(arg,2); arg2 = arg[2].arg_ptr.arg_arg; if (nothing_in_common(arg1,arg2)) arg->arg_flags &= ~AF_COMMON; if (arg->arg_type == O_ASSIGN) { arg[1].arg_flags |= AF_ARYOK; arg[2].arg_flags |= AF_ARYOK; } } else if (arg->arg_type == O_ASSIGN) arg[1].arg_flags |= AF_ARYOK; } else if (arg1->arg_type == O_ASLICE) { arg1->arg_type = O_LASLICE; if (arg->arg_type == O_ASSIGN) { dehoist(arg,2); arg[1].arg_flags |= AF_ARYOK; arg[2].arg_flags |= AF_ARYOK; } } else if (arg1->arg_type == O_HSLICE) { arg1->arg_type = O_LHSLICE; if (arg->arg_type == O_ASSIGN) { dehoist(arg,2); arg[1].arg_flags |= AF_ARYOK; arg[2].arg_flags |= AF_ARYOK; } } else if ((arg->arg_type == O_DEFINED || arg->arg_type == O_UNDEF) && (arg1->arg_type == (perldb ? O_DBSUBR : O_SUBR)) ) { arg[1].arg_type |= A_DONT; } else if (arg1->arg_type == O_SUBSTR || arg1->arg_type == O_VEC) { (void)l(arg1); Renewc(arg1->arg_ptr.arg_str, 1, struct lstring, STR); /* grow string struct to hold an lstring struct */ } else if (arg1->arg_type == O_ASSIGN) /*SUPPRESS 530*/ ; else { (void)sprintf(tokenbuf, "Illegal expression (%s) as lvalue",opname[arg1->arg_type]); yyerror(tokenbuf); return arg; } arg[1].arg_type = A_LEXPR | (arg[1].arg_type & A_DONT); if (arg->arg_type == O_ASSIGN && (arg1[1].arg_flags & AF_ARYOK)) { arg[1].arg_flags |= AF_ARYOK; if (arg->arg_len > 1) arg[2].arg_flags |= AF_ARYOK; } #ifdef DEBUGGING if (debug & 16) fprintf(stderr,"lval LEXPR\n"); #endif return arg; } if (i == A_STAR || i == A_LSTAR) { arg[1].arg_type = A_LSTAR | (arg[1].arg_type & A_DONT); return arg; } /* not an array reference, should be a register name */ if (i != A_STAB && i != A_LVAL) { (void)sprintf(tokenbuf, "Illegal item (%s) as lvalue",argname[arg[1].arg_type&A_MASK]); yyerror(tokenbuf); return arg; } arg[1].arg_type = A_LVAL | (arg[1].arg_type & A_DONT); #ifdef DEBUGGING if (debug & 16) fprintf(stderr,"lval LVAL\n"); #endif return arg; } ARG * fixl(type,arg) int type; ARG *arg; { if (type == O_DEFINED || type == O_UNDEF) { if (arg->arg_type != O_ITEM) arg = hide_ary(arg); if (arg->arg_type == O_ITEM) { type = arg[1].arg_type & A_MASK; if (type == A_EXPR || type == A_LEXPR) arg[1].arg_type = A_LEXPR|A_DONT; } } return arg; } void dehoist(arg,i) ARG *arg; { ARG *tmparg; if (arg[i].arg_type != A_EXPR) { /* dehoist */ tmparg = make_op(O_ITEM,1,Nullarg,Nullarg,Nullarg); tmparg[1] = arg[i]; arg[i].arg_ptr.arg_arg = tmparg; arg[i].arg_type = A_EXPR; } } ARG * addflags(i,flags,arg) register ARG *arg; { arg[i].arg_flags |= flags; return arg; } ARG * hide_ary(arg) ARG *arg; { if (arg->arg_type == O_ARRAY || arg->arg_type == O_HASH) return make_op(O_ITEM,1,arg,Nullarg,Nullarg); return arg; } /* maybe do a join on multiple array dimensions */ ARG * jmaybe(arg) register ARG *arg; { if (arg && arg->arg_type == O_COMMA) { arg = listish(arg); arg = make_op(O_JOIN, 2, stab2arg(A_STAB,stabent(";",TRUE)), make_list(arg), Nullarg); } return arg; } ARG * make_list(arg) register ARG *arg; { register int i; register ARG *node; register ARG *nxtnode; register int j; STR *tmpstr; if (!arg) { arg = op_new(0); arg->arg_type = O_LIST; } if (arg->arg_type != O_COMMA) { if (arg->arg_type != O_ARRAY) arg->arg_flags |= AF_LISTISH; /* see listish() below */ arg->arg_flags |= AF_LISTISH; /* see listish() below */ return arg; } for (i = 2, node = arg; ; i++) { if (node->arg_len < 2) break; if (node[1].arg_type != A_EXPR) break; node = node[1].arg_ptr.arg_arg; if (node->arg_type != O_COMMA) break; } if (i > 2) { node = arg; arg = op_new(i); tmpstr = arg->arg_ptr.arg_str; StructCopy(node, arg, ARG); /* copy everything except the STR */ arg->arg_ptr.arg_str = tmpstr; for (j = i; ; ) { StructCopy(node+2, arg+j, ARG); arg[j].arg_flags |= AF_ARYOK; --j; /* Bug in Xenix compiler */ if (j < 2) { StructCopy(node+1, arg+1, ARG); free_arg(node); break; } nxtnode = node[1].arg_ptr.arg_arg; free_arg(node); node = nxtnode; } } arg[1].arg_flags |= AF_ARYOK; arg[2].arg_flags |= AF_ARYOK; arg->arg_type = O_LIST; arg->arg_len = i; str_free(arg->arg_ptr.arg_str); arg->arg_ptr.arg_str = Nullstr; return arg; } /* turn a single item into a list */ ARG * listish(arg) ARG *arg; { if (arg && arg->arg_flags & AF_LISTISH) arg = make_op(O_LIST,1,arg,Nullarg,Nullarg); return arg; } ARG * maybelistish(optype, arg) int optype; ARG *arg; { ARG *tmparg = arg; if (optype == O_RETURN && arg->arg_type == O_ITEM && arg[1].arg_type == A_EXPR && (tmparg = arg[1].arg_ptr.arg_arg) && ((tmparg->arg_flags & AF_LISTISH) || (tmparg->arg_type == O_ARRAY) )) { tmparg = listish(tmparg); free_arg(arg); arg = tmparg; } else if (optype == O_PRTF || (arg->arg_type == O_ASLICE || arg->arg_type == O_HSLICE || arg->arg_type == O_F_OR_R) ) arg = listish(arg); return arg; } /* mark list of local variables */ ARG * localize(arg) ARG *arg; { - arg->arg_flags |= AF_LOCAL; + arg->arg_flags |= AF_LOCAL_XX; return arg; } ARG * rcatmaybe(arg) ARG *arg; { ARG *arg2; if (arg->arg_type == O_CONCAT && arg[2].arg_type == A_EXPR) { arg2 = arg[2].arg_ptr.arg_arg; if (arg2->arg_type == O_ITEM && arg2[1].arg_type == A_READ) { arg->arg_type = O_RCAT; arg[2].arg_type = arg2[1].arg_type; arg[2].arg_ptr = arg2[1].arg_ptr; free_arg(arg2); } } return arg; } ARG * stab2arg(atype,stab) int atype; register STAB *stab; { register ARG *arg; arg = op_new(1); arg->arg_type = O_ITEM; arg[1].arg_type = atype; arg[1].arg_ptr.arg_stab = stab; return arg; } ARG * cval_to_arg(cval) register char *cval; { register ARG *arg; arg = op_new(1); arg->arg_type = O_ITEM; arg[1].arg_type = A_SINGLE; arg[1].arg_ptr.arg_str = str_make(cval,0); Safefree(cval); return arg; } ARG * op_new(numargs) int numargs; { register ARG *arg; Newz(203,arg, numargs + 1, ARG); arg->arg_ptr.arg_str = Str_new(21,0); arg->arg_len = numargs; return arg; } void free_arg(arg) ARG *arg; { str_free(arg->arg_ptr.arg_str); Safefree(arg); } ARG * make_match(type,expr,spat) int type; ARG *expr; SPAT *spat; { register ARG *arg; arg = make_op(type,2,expr,Nullarg,Nullarg); arg[2].arg_type = A_SPAT|A_DONT; arg[2].arg_ptr.arg_spat = spat; #ifdef DEBUGGING if (debug & 16) fprintf(stderr,"make_match SPAT=%lx\n",(long)spat); #endif if (type == O_SUBST || type == O_NSUBST) { if (arg[1].arg_type != A_STAB) { yyerror("Illegal lvalue"); } arg[1].arg_type = A_LVAL; } return arg; } ARG * cmd_to_arg(cmd) CMD *cmd; { register ARG *arg; arg = op_new(1); arg->arg_type = O_ITEM; arg[1].arg_type = A_CMD; arg[1].arg_ptr.arg_cmd = cmd; return arg; } /* Check two expressions to see if there is any identifier in common */ static int nothing_in_common(arg1,arg2) ARG *arg1; ARG *arg2; { static int thisexpr = 0; /* I don't care if this wraps */ thisexpr++; if (arg_common(arg1,thisexpr,1)) return 0; /* hit eval or do {} */ stab_lastexpr(defstab) = thisexpr; /* pretend to hit @_ */ if (arg_common(arg2,thisexpr,0)) return 0; /* hit identifier again */ return 1; } /* Recursively descend an expression and mark any identifier or check * it to see if it was marked already. */ static int arg_common(arg,exprnum,marking) register ARG *arg; int exprnum; int marking; { register int i; if (!arg) return 0; for (i = arg->arg_len; i >= 1; i--) { switch (arg[i].arg_type & A_MASK) { case A_NULL: break; case A_LEXPR: case A_EXPR: if (arg_common(arg[i].arg_ptr.arg_arg,exprnum,marking)) return 1; break; case A_CMD: return 1; /* assume hanky panky */ case A_STAR: case A_LSTAR: case A_STAB: case A_LVAL: case A_ARYLEN: case A_LARYLEN: if (marking) stab_lastexpr(arg[i].arg_ptr.arg_stab) = exprnum; else if (stab_lastexpr(arg[i].arg_ptr.arg_stab) == exprnum) return 1; break; case A_DOUBLE: case A_BACKTICK: { register char *s = arg[i].arg_ptr.arg_str->str_ptr; register char *send = s + arg[i].arg_ptr.arg_str->str_cur; register STAB *stab; while (*s) { if (*s == '$' && s[1]) { s = scanident(s,send,tokenbuf); stab = stabent(tokenbuf,TRUE); if (marking) stab_lastexpr(stab) = exprnum; else if (stab_lastexpr(stab) == exprnum) return 1; continue; } else if (*s == '\\' && s[1]) s++; s++; } } break; case A_SPAT: if (spat_common(arg[i].arg_ptr.arg_spat,exprnum,marking)) return 1; break; case A_READ: case A_INDREAD: case A_GLOB: case A_WORD: case A_SINGLE: break; } } switch (arg->arg_type) { case O_ARRAY: case O_LARRAY: if ((arg[1].arg_type & A_MASK) == A_STAB) (void)aadd(arg[1].arg_ptr.arg_stab); break; case O_HASH: case O_LHASH: if ((arg[1].arg_type & A_MASK) == A_STAB) (void)hadd(arg[1].arg_ptr.arg_stab); break; case O_EVAL: case O_SUBR: case O_DBSUBR: return 1; } return 0; } static int spat_common(spat,exprnum,marking) register SPAT *spat; int exprnum; int marking; { if (spat->spat_runtime) if (arg_common(spat->spat_runtime,exprnum,marking)) return 1; if (spat->spat_repl) { if (arg_common(spat->spat_repl,exprnum,marking)) return 1; } return 0; } Index: head/gnu/usr.bin/perl/perl/doarg.c =================================================================== --- head/gnu/usr.bin/perl/perl/doarg.c (revision 2652) +++ head/gnu/usr.bin/perl/perl/doarg.c (revision 2653) @@ -1,1849 +1,1852 @@ -/* $RCSfile: doarg.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:35 $ +/* $RCSfile: doarg.c,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:32 $ * * Copyright (c) 1991, Larry Wall * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. * * $Log: doarg.c,v $ + * Revision 1.1.1.1 1994/09/10 06:27:32 gclarkii + * Initial import of Perl 4.046 bmaked + * * Revision 1.1.1.1 1993/08/23 21:29:35 nate * PERL! * * Revision 4.0.1.8 1993/02/05 19:32:27 lwall * patch36: substitution didn't always invalidate numericity * * Revision 4.0.1.7 92/06/11 21:07:11 lwall * patch34: join with null list attempted negative allocation * patch34: sprintf("%6.4s", "abcdefg") didn't print "abcd " * * Revision 4.0.1.6 92/06/08 12:34:30 lwall * patch20: removed implicit int declarations on funcions * patch20: pattern modifiers i and o didn't interact right * patch20: join() now pre-extends target string to avoid excessive copying * patch20: fixed confusion between a *var's real name and its effective name * patch20: subroutines didn't localize $`, $&, $', $1 et al correctly * patch20: usersub routines didn't reclaim temp values soon enough * patch20: ($<,$>) = ... didn't work on some architectures * patch20: added Atari ST portability * * Revision 4.0.1.5 91/11/11 16:31:58 lwall * patch19: added little-endian pack/unpack options * * Revision 4.0.1.4 91/11/05 16:35:06 lwall * patch11: /$foo/o optimizer could access deallocated data * patch11: minimum match length calculation in regexp is now cumulative * patch11: added some support for 64-bit integers * patch11: prepared for ctype implementations that don't define isascii() * patch11: sprintf() now supports any length of s field * patch11: indirect subroutine calls through magic vars (e.g. &$1) didn't work * patch11: defined(&$foo) and undef(&$foo) didn't work * * Revision 4.0.1.3 91/06/10 01:18:41 lwall * patch10: pack(hh,1) dumped core * * Revision 4.0.1.2 91/06/07 10:42:17 lwall * patch4: new copyright notice * patch4: // wouldn't use previous pattern if it started with a null character * patch4: //o and s///o now optimize themselves fully at runtime * patch4: added global modifier for pattern matches * patch4: undef @array disabled "@array" interpolation * patch4: chop("") was returning "\0" rather than "" * patch4: vector logical operations &, | and ^ sometimes returned null string * patch4: syscall couldn't pass numbers with most significant bit set on sparcs * * Revision 4.0.1.1 91/04/11 17:40:14 lwall * patch1: fixed undefined environ problem * patch1: fixed debugger coredump on subroutines * * Revision 4.0 91/03/20 01:06:42 lwall * 4.0 baseline. * */ #include "EXTERN.h" #include "perl.h" #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX) #include #endif extern unsigned char fold[]; #ifdef BUGGY_MSC #pragma function(memcmp) #endif /* BUGGY_MSC */ static void doencodes(); int do_subst(str,arg,sp) STR *str; ARG *arg; int sp; { register SPAT *spat; SPAT *rspat; register STR *dstr; register char *s = str_get(str); char *strend = s + str->str_cur; register char *m; char *c; register char *d; int clen; int iters = 0; int maxiters = (strend - s) + 10; register int i; bool once; char *orig; int safebase; rspat = spat = arg[2].arg_ptr.arg_spat; if (!spat || !s) fatal("panic: do_subst"); else if (spat->spat_runtime) { nointrp = "|)"; (void)eval(spat->spat_runtime,G_SCALAR,sp); m = str_get(dstr = stack->ary_array[sp+1]); nointrp = ""; if (spat->spat_regexp) { regfree(spat->spat_regexp); spat->spat_regexp = Null(REGEXP*); /* required if regcomp pukes */ } spat->spat_regexp = regcomp(m,m+dstr->str_cur, spat->spat_flags & SPAT_FOLD); if (spat->spat_flags & SPAT_KEEP) { if (!(spat->spat_flags & SPAT_FOLD)) scanconst(spat, m, dstr->str_cur); arg_free(spat->spat_runtime); /* it won't change, so */ spat->spat_runtime = Nullarg; /* no point compiling again */ hoistmust(spat); if (curcmd->c_expr && (curcmd->c_flags & CF_OPTIMIZE) == CFT_EVAL) { curcmd->c_flags &= ~CF_OPTIMIZE; opt_arg(curcmd, 1, curcmd->c_type == C_EXPR); } } } #ifdef DEBUGGING if (debug & 8) { deb("2.SPAT /%s/\n",spat->spat_regexp->precomp); } #endif safebase = ((!spat->spat_regexp || !spat->spat_regexp->nparens) && !sawampersand); if (!spat->spat_regexp->prelen && lastspat) spat = lastspat; orig = m = s; if (hint) { if (hint < s || hint > strend) fatal("panic: hint in do_match"); s = hint; hint = Nullch; if (spat->spat_regexp->regback >= 0) { s -= spat->spat_regexp->regback; if (s < m) s = m; } else s = m; } else if (spat->spat_short) { if (spat->spat_flags & SPAT_SCANFIRST) { if (str->str_pok & SP_STUDIED) { if (screamfirst[spat->spat_short->str_rare] < 0) goto nope; else if (!(s = screaminstr(str,spat->spat_short))) goto nope; } #ifndef lint else if (!(s = fbminstr((unsigned char*)s, (unsigned char*)strend, spat->spat_short))) goto nope; #endif if (s && spat->spat_regexp->regback >= 0) { ++spat->spat_short->str_u.str_useful; s -= spat->spat_regexp->regback; if (s < m) s = m; } else s = m; } else if (!multiline && (*spat->spat_short->str_ptr != *s || bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) )) goto nope; if (--spat->spat_short->str_u.str_useful < 0) { str_free(spat->spat_short); spat->spat_short = Nullstr; /* opt is being useless */ } } once = !(rspat->spat_flags & SPAT_GLOBAL); if (rspat->spat_flags & SPAT_CONST) { /* known replacement string? */ if ((rspat->spat_repl[1].arg_type & A_MASK) == A_SINGLE) dstr = rspat->spat_repl[1].arg_ptr.arg_str; else { /* constant over loop, anyway */ (void)eval(rspat->spat_repl,G_SCALAR,sp); dstr = stack->ary_array[sp+1]; } c = str_get(dstr); clen = dstr->str_cur; if (clen <= spat->spat_regexp->minlen) { /* can do inplace substitution */ if (regexec(spat->spat_regexp, s, strend, orig, 0, str->str_pok & SP_STUDIED ? str : Nullstr, safebase)) { if (spat->spat_regexp->subbase) /* oops, no we can't */ goto long_way; d = s; lastspat = spat; str->str_pok = SP_VALID; /* disable possible screamer */ if (once) { m = spat->spat_regexp->startp[0]; d = spat->spat_regexp->endp[0]; s = orig; if (m - s > strend - d) { /* faster to shorten from end */ if (clen) { Copy(c, m, clen, char); m += clen; } i = strend - d; if (i > 0) { Move(d, m, i, char); m += i; } *m = '\0'; str->str_cur = m - s; STABSET(str); str_numset(arg->arg_ptr.arg_str, 1.0); stack->ary_array[++sp] = arg->arg_ptr.arg_str; str->str_nok = 0; return sp; } /*SUPPRESS 560*/ else if (i = m - s) { /* faster from front */ d -= clen; m = d; str_chop(str,d-i); s += i; while (i--) *--d = *--s; if (clen) Copy(c, m, clen, char); STABSET(str); str_numset(arg->arg_ptr.arg_str, 1.0); stack->ary_array[++sp] = arg->arg_ptr.arg_str; str->str_nok = 0; return sp; } else if (clen) { d -= clen; str_chop(str,d); Copy(c,d,clen,char); STABSET(str); str_numset(arg->arg_ptr.arg_str, 1.0); stack->ary_array[++sp] = arg->arg_ptr.arg_str; str->str_nok = 0; return sp; } else { str_chop(str,d); STABSET(str); str_numset(arg->arg_ptr.arg_str, 1.0); stack->ary_array[++sp] = arg->arg_ptr.arg_str; str->str_nok = 0; return sp; } /* NOTREACHED */ } do { if (iters++ > maxiters) fatal("Substitution loop"); m = spat->spat_regexp->startp[0]; /*SUPPRESS 560*/ if (i = m - s) { if (s != d) Move(s,d,i,char); d += i; } if (clen) { Copy(c,d,clen,char); d += clen; } s = spat->spat_regexp->endp[0]; } while (regexec(spat->spat_regexp, s, strend, orig, s == m, Nullstr, TRUE)); /* (don't match same null twice) */ if (s != d) { i = strend - s; str->str_cur = d - str->str_ptr + i; Move(s,d,i+1,char); /* include the Null */ } STABSET(str); str_numset(arg->arg_ptr.arg_str, (double)iters); stack->ary_array[++sp] = arg->arg_ptr.arg_str; str->str_nok = 0; return sp; } str_numset(arg->arg_ptr.arg_str, 0.0); stack->ary_array[++sp] = arg->arg_ptr.arg_str; return sp; } } else c = Nullch; if (regexec(spat->spat_regexp, s, strend, orig, 0, str->str_pok & SP_STUDIED ? str : Nullstr, safebase)) { long_way: dstr = Str_new(25,str_len(str)); str_nset(dstr,m,s-m); if (spat->spat_regexp->subbase) curspat = spat; lastspat = spat; do { if (iters++ > maxiters) fatal("Substitution loop"); if (spat->spat_regexp->subbase && spat->spat_regexp->subbase != orig) { m = s; s = orig; orig = spat->spat_regexp->subbase; s = orig + (m - s); strend = s + (strend - m); } m = spat->spat_regexp->startp[0]; str_ncat(dstr,s,m-s); s = spat->spat_regexp->endp[0]; if (c) { if (clen) str_ncat(dstr,c,clen); } else { char *mysubbase = spat->spat_regexp->subbase; spat->spat_regexp->subbase = Nullch; /* so recursion works */ (void)eval(rspat->spat_repl,G_SCALAR,sp); str_scat(dstr,stack->ary_array[sp+1]); if (spat->spat_regexp->subbase) Safefree(spat->spat_regexp->subbase); spat->spat_regexp->subbase = mysubbase; } if (once) break; } while (regexec(spat->spat_regexp, s, strend, orig, s == m, Nullstr, safebase)); str_ncat(dstr,s,strend - s); str_replace(str,dstr); STABSET(str); str_numset(arg->arg_ptr.arg_str, (double)iters); stack->ary_array[++sp] = arg->arg_ptr.arg_str; str->str_nok = 0; return sp; } str_numset(arg->arg_ptr.arg_str, 0.0); stack->ary_array[++sp] = arg->arg_ptr.arg_str; return sp; nope: ++spat->spat_short->str_u.str_useful; str_numset(arg->arg_ptr.arg_str, 0.0); stack->ary_array[++sp] = arg->arg_ptr.arg_str; return sp; } #ifdef BUGGY_MSC #pragma intrinsic(memcmp) #endif /* BUGGY_MSC */ int do_trans(str,arg) STR *str; ARG *arg; { register short *tbl; register char *s; register int matches = 0; register int ch; register char *send; register char *d; register int squash = arg[2].arg_len & 1; tbl = (short*) arg[2].arg_ptr.arg_cval; s = str_get(str); send = s + str->str_cur; if (!tbl || !s) fatal("panic: do_trans"); #ifdef DEBUGGING if (debug & 8) { deb("2.TBL\n"); } #endif if (!arg[2].arg_len) { while (s < send) { if ((ch = tbl[*s & 0377]) >= 0) { matches++; *s = ch; } s++; } } else { d = s; while (s < send) { if ((ch = tbl[*s & 0377]) >= 0) { *d = ch; if (matches++ && squash) { if (d[-1] == *d) matches--; else d++; } else d++; } else if (ch == -1) /* -1 is unmapped character */ *d++ = *s; /* -2 is delete character */ s++; } matches += send - d; /* account for disappeared chars */ *d = '\0'; str->str_cur = d - str->str_ptr; } STABSET(str); return matches; } void do_join(str,arglast) register STR *str; int *arglast; { register STR **st = stack->ary_array; int sp = arglast[1]; register int items = arglast[2] - sp; register char *delim = str_get(st[sp]); register STRLEN len; int delimlen = st[sp]->str_cur; st += sp + 1; len = (items > 0 ? (delimlen * (items - 1) ) : 0); if (str->str_len < len + items) { /* current length is way too short */ while (items-- > 0) { if (*st) len += (*st)->str_cur; st++; } STR_GROW(str, len + 1); /* so try to pre-extend */ items = arglast[2] - sp; st -= items; } if (items-- > 0) str_sset(str, *st++); else str_set(str,""); len = delimlen; if (len) { for (; items > 0; items--,st++) { str_ncat(str,delim,len); str_scat(str,*st); } } else { for (; items > 0; items--,st++) str_scat(str,*st); } STABSET(str); } void do_pack(str,arglast) register STR *str; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register int items; register char *pat = str_get(st[sp]); register char *patend = pat + st[sp]->str_cur; register int len; int datumtype; STR *fromstr; /*SUPPRESS 442*/ static char *null10 = "\0\0\0\0\0\0\0\0\0\0"; static char *space10 = " "; /* These must not be in registers: */ char achar; short ashort; int aint; unsigned int auint; long along; unsigned long aulong; #ifdef QUAD quad aquad; unsigned quad auquad; #endif char *aptr; float afloat; double adouble; items = arglast[2] - sp; st += ++sp; str_nset(str,"",0); while (pat < patend) { #define NEXTFROM (items-- > 0 ? *st++ : &str_no) datumtype = *pat++; if (*pat == '*') { len = index("@Xxu",datumtype) ? 0 : items; pat++; } else if (isDIGIT(*pat)) { len = *pat++ - '0'; while (isDIGIT(*pat)) len = (len * 10) + (*pat++ - '0'); } else len = 1; switch(datumtype) { default: break; case '%': fatal("% may only be used in unpack"); case '@': len -= str->str_cur; if (len > 0) goto grow; len = -len; if (len > 0) goto shrink; break; case 'X': shrink: if (str->str_cur < len) fatal("X outside of string"); str->str_cur -= len; str->str_ptr[str->str_cur] = '\0'; break; case 'x': grow: while (len >= 10) { str_ncat(str,null10,10); len -= 10; } str_ncat(str,null10,len); break; case 'A': case 'a': fromstr = NEXTFROM; aptr = str_get(fromstr); if (pat[-1] == '*') len = fromstr->str_cur; if (fromstr->str_cur > len) str_ncat(str,aptr,len); else { str_ncat(str,aptr,fromstr->str_cur); len -= fromstr->str_cur; if (datumtype == 'A') { while (len >= 10) { str_ncat(str,space10,10); len -= 10; } str_ncat(str,space10,len); } else { while (len >= 10) { str_ncat(str,null10,10); len -= 10; } str_ncat(str,null10,len); } } break; case 'B': case 'b': { char *savepat = pat; int saveitems; fromstr = NEXTFROM; saveitems = items; aptr = str_get(fromstr); if (pat[-1] == '*') len = fromstr->str_cur; pat = aptr; aint = str->str_cur; str->str_cur += (len+7)/8; STR_GROW(str, str->str_cur + 1); aptr = str->str_ptr + aint; if (len > fromstr->str_cur) len = fromstr->str_cur; aint = len; items = 0; if (datumtype == 'B') { for (len = 0; len++ < aint;) { items |= *pat++ & 1; if (len & 7) items <<= 1; else { *aptr++ = items & 0xff; items = 0; } } } else { for (len = 0; len++ < aint;) { if (*pat++ & 1) items |= 128; if (len & 7) items >>= 1; else { *aptr++ = items & 0xff; items = 0; } } } if (aint & 7) { if (datumtype == 'B') items <<= 7 - (aint & 7); else items >>= 7 - (aint & 7); *aptr++ = items & 0xff; } pat = str->str_ptr + str->str_cur; while (aptr <= pat) *aptr++ = '\0'; pat = savepat; items = saveitems; } break; case 'H': case 'h': { char *savepat = pat; int saveitems; fromstr = NEXTFROM; saveitems = items; aptr = str_get(fromstr); if (pat[-1] == '*') len = fromstr->str_cur; pat = aptr; aint = str->str_cur; str->str_cur += (len+1)/2; STR_GROW(str, str->str_cur + 1); aptr = str->str_ptr + aint; if (len > fromstr->str_cur) len = fromstr->str_cur; aint = len; items = 0; if (datumtype == 'H') { for (len = 0; len++ < aint;) { if (isALPHA(*pat)) items |= ((*pat++ & 15) + 9) & 15; else items |= *pat++ & 15; if (len & 1) items <<= 4; else { *aptr++ = items & 0xff; items = 0; } } } else { for (len = 0; len++ < aint;) { if (isALPHA(*pat)) items |= (((*pat++ & 15) + 9) & 15) << 4; else items |= (*pat++ & 15) << 4; if (len & 1) items >>= 4; else { *aptr++ = items & 0xff; items = 0; } } } if (aint & 1) *aptr++ = items & 0xff; pat = str->str_ptr + str->str_cur; while (aptr <= pat) *aptr++ = '\0'; pat = savepat; items = saveitems; } break; case 'C': case 'c': while (len-- > 0) { fromstr = NEXTFROM; aint = (int)str_gnum(fromstr); achar = aint; str_ncat(str,&achar,sizeof(char)); } break; /* Float and double added by gnb@melba.bby.oz.au 22/11/89 */ case 'f': case 'F': while (len-- > 0) { fromstr = NEXTFROM; afloat = (float)str_gnum(fromstr); str_ncat(str, (char *)&afloat, sizeof (float)); } break; case 'd': case 'D': while (len-- > 0) { fromstr = NEXTFROM; adouble = (double)str_gnum(fromstr); str_ncat(str, (char *)&adouble, sizeof (double)); } break; case 'n': while (len-- > 0) { fromstr = NEXTFROM; ashort = (short)str_gnum(fromstr); #ifdef HAS_HTONS ashort = htons(ashort); #endif str_ncat(str,(char*)&ashort,sizeof(short)); } break; case 'v': while (len-- > 0) { fromstr = NEXTFROM; ashort = (short)str_gnum(fromstr); #ifdef HAS_HTOVS ashort = htovs(ashort); #endif str_ncat(str,(char*)&ashort,sizeof(short)); } break; case 'S': case 's': while (len-- > 0) { fromstr = NEXTFROM; ashort = (short)str_gnum(fromstr); str_ncat(str,(char*)&ashort,sizeof(short)); } break; case 'I': while (len-- > 0) { fromstr = NEXTFROM; auint = U_I(str_gnum(fromstr)); str_ncat(str,(char*)&auint,sizeof(unsigned int)); } break; case 'i': while (len-- > 0) { fromstr = NEXTFROM; aint = (int)str_gnum(fromstr); str_ncat(str,(char*)&aint,sizeof(int)); } break; case 'N': while (len-- > 0) { fromstr = NEXTFROM; aulong = U_L(str_gnum(fromstr)); #ifdef HAS_HTONL aulong = htonl(aulong); #endif str_ncat(str,(char*)&aulong,sizeof(unsigned long)); } break; case 'V': while (len-- > 0) { fromstr = NEXTFROM; aulong = U_L(str_gnum(fromstr)); #ifdef HAS_HTOVL aulong = htovl(aulong); #endif str_ncat(str,(char*)&aulong,sizeof(unsigned long)); } break; case 'L': while (len-- > 0) { fromstr = NEXTFROM; aulong = U_L(str_gnum(fromstr)); str_ncat(str,(char*)&aulong,sizeof(unsigned long)); } break; case 'l': while (len-- > 0) { fromstr = NEXTFROM; along = (long)str_gnum(fromstr); str_ncat(str,(char*)&along,sizeof(long)); } break; #ifdef QUAD case 'Q': while (len-- > 0) { fromstr = NEXTFROM; auquad = (unsigned quad)str_gnum(fromstr); str_ncat(str,(char*)&auquad,sizeof(unsigned quad)); } break; case 'q': while (len-- > 0) { fromstr = NEXTFROM; aquad = (quad)str_gnum(fromstr); str_ncat(str,(char*)&aquad,sizeof(quad)); } break; #endif /* QUAD */ case 'p': while (len-- > 0) { fromstr = NEXTFROM; aptr = str_get(fromstr); str_ncat(str,(char*)&aptr,sizeof(char*)); } break; case 'u': fromstr = NEXTFROM; aptr = str_get(fromstr); aint = fromstr->str_cur; STR_GROW(str,aint * 4 / 3); if (len <= 1) len = 45; else len = len / 3 * 3; while (aint > 0) { int todo; if (aint > len) todo = len; else todo = aint; doencodes(str, aptr, todo); aint -= todo; aptr += todo; } break; } } STABSET(str); } #undef NEXTFROM static void doencodes(str, s, len) register STR *str; register char *s; register int len; { char hunk[5]; *hunk = len + ' '; str_ncat(str, hunk, 1); hunk[4] = '\0'; while (len > 0) { hunk[0] = ' ' + (077 & (*s >> 2)); hunk[1] = ' ' + (077 & ((*s << 4) & 060 | (s[1] >> 4) & 017)); hunk[2] = ' ' + (077 & ((s[1] << 2) & 074 | (s[2] >> 6) & 03)); hunk[3] = ' ' + (077 & (s[2] & 077)); str_ncat(str, hunk, 4); s += 3; len -= 3; } for (s = str->str_ptr; *s; s++) { if (*s == ' ') *s = '`'; } str_ncat(str, "\n", 1); } void do_sprintf(str,len,sarg) register STR *str; register int len; register STR **sarg; { register char *s; register char *t; register char *f; bool dolong; #ifdef QUAD bool doquad; #endif /* QUAD */ char ch; static STR *sargnull = &str_no; register char *send; register STR *arg; char *xs; int xlen; int pre; int post; double value; str_set(str,""); len--; /* don't count pattern string */ t = s = str_get(*sarg); send = s + (*sarg)->str_cur; sarg++; for ( ; ; len--) { /*SUPPRESS 560*/ if (len <= 0 || !(arg = *sarg++)) arg = sargnull; /*SUPPRESS 530*/ for ( ; t < send && *t != '%'; t++) ; if (t >= send) break; /* end of format string, ignore extra args */ f = t; *buf = '\0'; xs = buf; #ifdef QUAD doquad = #endif /* QUAD */ dolong = FALSE; pre = post = 0; for (t++; t < send; t++) { switch (*t) { default: ch = *(++t); *t = '\0'; (void)sprintf(xs,f); len++, sarg--; xlen = strlen(xs); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': case '#': case '-': case '+': case ' ': continue; case 'l': #ifdef QUAD if (dolong) { dolong = FALSE; doquad = TRUE; } else #endif dolong = TRUE; continue; case 'c': ch = *(++t); *t = '\0'; xlen = (int)str_gnum(arg); if (strEQ(f,"%c")) { /* some printfs fail on null chars */ *xs = xlen; xs[1] = '\0'; xlen = 1; } else { (void)sprintf(xs,f,xlen); xlen = strlen(xs); } break; case 'D': dolong = TRUE; /* FALL THROUGH */ case 'd': ch = *(++t); *t = '\0'; #ifdef QUAD if (doquad) (void)sprintf(buf,s,(quad)str_gnum(arg)); else #endif if (dolong) (void)sprintf(xs,f,(long)str_gnum(arg)); else (void)sprintf(xs,f,(int)str_gnum(arg)); xlen = strlen(xs); break; case 'X': case 'O': dolong = TRUE; /* FALL THROUGH */ case 'x': case 'o': case 'u': ch = *(++t); *t = '\0'; value = str_gnum(arg); #ifdef QUAD if (doquad) (void)sprintf(buf,s,(unsigned quad)value); else #endif if (dolong) (void)sprintf(xs,f,U_L(value)); else (void)sprintf(xs,f,U_I(value)); xlen = strlen(xs); break; case 'E': case 'e': case 'f': case 'G': case 'g': ch = *(++t); *t = '\0'; (void)sprintf(xs,f,str_gnum(arg)); xlen = strlen(xs); break; case 's': ch = *(++t); *t = '\0'; xs = str_get(arg); xlen = arg->str_cur; if (*xs == 'S' && xs[1] == 't' && xs[2] == 'B' && xs[3] == '\0' && xlen == sizeof(STBP)) { STR *tmpstr = Str_new(24,0); stab_efullname(tmpstr, ((STAB*)arg)); /* a stab value! */ sprintf(tokenbuf,"*%s",tmpstr->str_ptr); /* reformat to non-binary */ xs = tokenbuf; xlen = strlen(tokenbuf); str_free(tmpstr); } if (strEQ(f,"%s")) { /* some printfs fail on >128 chars */ break; /* so handle simple cases */ } else if (f[1] == '-') { char *mp = index(f, '.'); int min = atoi(f+2); if (mp) { int max = atoi(mp+1); if (xlen > max) xlen = max; } if (xlen < min) post = min - xlen; break; } else if (isDIGIT(f[1])) { char *mp = index(f, '.'); int min = atoi(f+1); if (mp) { int max = atoi(mp+1); if (xlen > max) xlen = max; } if (xlen < min) pre = min - xlen; break; } strcpy(tokenbuf+64,f); /* sprintf($s,...$s...) */ *t = ch; (void)sprintf(buf,tokenbuf+64,xs); xs = buf; xlen = strlen(xs); break; } /* end of switch, copy results */ *t = ch; STR_GROW(str, str->str_cur + (f - s) + xlen + 1 + pre + post); str_ncat(str, s, f - s); if (pre) { repeatcpy(str->str_ptr + str->str_cur, " ", 1, pre); str->str_cur += pre; } str_ncat(str, xs, xlen); if (post) { repeatcpy(str->str_ptr + str->str_cur, " ", 1, post); str->str_cur += post; } s = t; break; /* break from for loop */ } } str_ncat(str, s, t - s); STABSET(str); } STR * do_push(ary,arglast) register ARRAY *ary; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register int items = arglast[2] - sp; register STR *str = &str_undef; for (st += ++sp; items > 0; items--,st++) { str = Str_new(26,0); if (*st) str_sset(str,*st); (void)apush(ary,str); } return str; } void do_unshift(ary,arglast) register ARRAY *ary; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register int items = arglast[2] - sp; register STR *str; register int i; aunshift(ary,items); i = 0; for (st += ++sp; i < items; i++,st++) { str = Str_new(27,0); str_sset(str,*st); (void)astore(ary,i,str); } } int do_subr(arg,gimme,arglast) register ARG *arg; int gimme; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register int items = arglast[2] - sp; register SUBR *sub; SPAT * VOLATILE oldspat = curspat; STR *str; STAB *stab; int oldsave = savestack->ary_fill; int oldtmps_base = tmps_base; int hasargs = ((arg[2].arg_type & A_MASK) != A_NULL); register CSV *csv; if ((arg[1].arg_type & A_MASK) == A_WORD) stab = arg[1].arg_ptr.arg_stab; else { STR *tmpstr = STAB_STR(arg[1].arg_ptr.arg_stab); if (tmpstr) stab = stabent(str_get(tmpstr),TRUE); else stab = Nullstab; } if (!stab) fatal("Undefined subroutine called"); if (!(sub = stab_sub(stab))) { STR *tmpstr = arg[0].arg_ptr.arg_str; stab_efullname(tmpstr, stab); fatal("Undefined subroutine \"%s\" called",tmpstr->str_ptr); } if (arg->arg_type == O_DBSUBR && !sub->usersub) { str = stab_val(DBsub); saveitem(str); stab_efullname(str,stab); sub = stab_sub(DBsub); if (!sub) fatal("No DBsub routine"); } str = Str_new(15, sizeof(CSV)); str->str_state = SS_SCSV; (void)apush(savestack,str); csv = (CSV*)str->str_ptr; csv->sub = sub; csv->stab = stab; csv->curcsv = curcsv; csv->curcmd = curcmd; csv->depth = sub->depth; csv->wantarray = gimme; csv->hasargs = hasargs; curcsv = csv; tmps_base = tmps_max; if (sub->usersub) { csv->hasargs = 0; csv->savearray = Null(ARRAY*);; csv->argarray = Null(ARRAY*); st[sp] = arg->arg_ptr.arg_str; if (!hasargs) items = 0; sp = (*sub->usersub)(sub->userindex,sp,items); } else { if (hasargs) { csv->savearray = stab_xarray(defstab); csv->argarray = afake(defstab, items, &st[sp+1]); stab_xarray(defstab) = csv->argarray; } sub->depth++; if (sub->depth >= 2) { /* save temporaries on recursion? */ if (sub->depth == 100 && dowarn) warn("Deep recursion on subroutine \"%s\"",stab_ename(stab)); savelist(sub->tosave->ary_array,sub->tosave->ary_fill); } sp = cmd_exec(sub->cmd,gimme, --sp); /* so do it already */ } st = stack->ary_array; tmps_base = oldtmps_base; for (items = arglast[0] + 1; items <= sp; items++) st[items] = str_mortal(st[items]); /* in case restore wipes old str */ restorelist(oldsave); curspat = oldspat; return sp; } int do_assign(arg,gimme,arglast) register ARG *arg; int gimme; int *arglast; { register STR **st = stack->ary_array; STR **firstrelem = st + arglast[1] + 1; STR **firstlelem = st + arglast[0] + 1; STR **lastrelem = st + arglast[2]; STR **lastlelem = st + arglast[1]; register STR **relem; register STR **lelem; register STR *str; register ARRAY *ary; register int makelocal; HASH *hash; int i; - makelocal = (arg->arg_flags & AF_LOCAL) != 0; + makelocal = (arg->arg_flags & AF_LOCAL_XX) != 0; localizing = makelocal; delaymagic = DM_DELAY; /* catch simultaneous items */ /* If there's a common identifier on both sides we have to take * special care that assigning the identifier on the left doesn't * clobber a value on the right that's used later in the list. */ if (arg->arg_flags & AF_COMMON) { for (relem = firstrelem; relem <= lastrelem; relem++) { /*SUPPRESS 560*/ if (str = *relem) *relem = str_mortal(str); } } relem = firstrelem; lelem = firstlelem; ary = Null(ARRAY*); hash = Null(HASH*); while (lelem <= lastlelem) { str = *lelem++; if (str->str_state >= SS_HASH) { if (str->str_state == SS_ARY) { if (makelocal) ary = saveary(str->str_u.str_stab); else { ary = stab_array(str->str_u.str_stab); ary->ary_fill = -1; } i = 0; while (relem <= lastrelem) { /* gobble up all the rest */ str = Str_new(28,0); if (*relem) str_sset(str,*relem); *(relem++) = str; (void)astore(ary,i++,str); } } else if (str->str_state == SS_HASH) { char *tmps; STR *tmpstr; int magic = 0; STAB *tmpstab = str->str_u.str_stab; if (makelocal) hash = savehash(str->str_u.str_stab); else { hash = stab_hash(str->str_u.str_stab); if (tmpstab == envstab) { magic = 'E'; environ[0] = Nullch; } else if (tmpstab == sigstab) { magic = 'S'; #ifndef NSIG #define NSIG 32 #endif for (i = 1; i < NSIG; i++) signal(i, SIG_DFL); /* crunch, crunch, crunch */ } #ifdef SOME_DBM else if (hash->tbl_dbm) magic = 'D'; #endif hclear(hash, magic == 'D'); /* wipe any dbm file too */ } while (relem < lastrelem) { /* gobble up all the rest */ if (*relem) str = *(relem++); else str = &str_no, relem++; tmps = str_get(str); tmpstr = Str_new(29,0); if (*relem) str_sset(tmpstr,*relem); /* value */ *(relem++) = tmpstr; (void)hstore(hash,tmps,str->str_cur,tmpstr,0); if (magic) { str_magic(tmpstr, tmpstab, magic, tmps, str->str_cur); stabset(tmpstr->str_magic, tmpstr); } } } else fatal("panic: do_assign"); } else { if (makelocal) saveitem(str); if (relem <= lastrelem) { str_sset(str, *relem); *(relem++) = str; } else { str_sset(str, &str_undef); if (gimme == G_ARRAY) { i = ++lastrelem - firstrelem; relem++; /* tacky, I suppose */ astore(stack,i,str); if (st != stack->ary_array) { st = stack->ary_array; firstrelem = st + arglast[1] + 1; firstlelem = st + arglast[0] + 1; lastlelem = st + arglast[1]; lastrelem = st + i; relem = lastrelem + 1; } } } STABSET(str); } } if (delaymagic & ~DM_DELAY) { if (delaymagic & DM_UID) { #ifdef HAS_SETREUID (void)setreuid(uid,euid); #else /* not HAS_SETREUID */ #ifdef HAS_SETRUID if ((delaymagic & DM_UID) == DM_RUID) { (void)setruid(uid); delaymagic =~ DM_RUID; } #endif /* HAS_SETRUID */ #ifdef HAS_SETEUID if ((delaymagic & DM_UID) == DM_EUID) { (void)seteuid(uid); delaymagic =~ DM_EUID; } #endif /* HAS_SETEUID */ if (delaymagic & DM_UID) { if (uid != euid) fatal("No setreuid available"); (void)setuid(uid); } #endif /* not HAS_SETREUID */ uid = (int)getuid(); euid = (int)geteuid(); } if (delaymagic & DM_GID) { #ifdef HAS_SETREGID (void)setregid(gid,egid); #else /* not HAS_SETREGID */ #ifdef HAS_SETRGID if ((delaymagic & DM_GID) == DM_RGID) { (void)setrgid(gid); delaymagic =~ DM_RGID; } #endif /* HAS_SETRGID */ #ifdef HAS_SETEGID if ((delaymagic & DM_GID) == DM_EGID) { (void)setegid(gid); delaymagic =~ DM_EGID; } #endif /* HAS_SETEGID */ if (delaymagic & DM_GID) { if (gid != egid) fatal("No setregid available"); (void)setgid(gid); } #endif /* not HAS_SETREGID */ gid = (int)getgid(); egid = (int)getegid(); } } delaymagic = 0; localizing = FALSE; if (gimme == G_ARRAY) { i = lastrelem - firstrelem + 1; if (ary || hash) Copy(firstrelem, firstlelem, i, STR*); return arglast[0] + i; } else { str_numset(arg->arg_ptr.arg_str,(double)(arglast[2] - arglast[1])); *firstlelem = arg->arg_ptr.arg_str; return arglast[0] + 1; } } int /*SUPPRESS 590*/ do_study(str,arg,gimme,arglast) STR *str; ARG *arg; int gimme; int *arglast; { register unsigned char *s; register int pos = str->str_cur; register int ch; register int *sfirst; register int *snext; static int maxscream = -1; static STR *lastscream = Nullstr; int retval; int retarg = arglast[0] + 1; #ifndef lint s = (unsigned char*)(str_get(str)); #else s = Null(unsigned char*); #endif if (lastscream) lastscream->str_pok &= ~SP_STUDIED; lastscream = str; if (pos <= 0) { retval = 0; goto ret; } if (pos > maxscream) { if (maxscream < 0) { maxscream = pos + 80; New(301,screamfirst, 256, int); New(302,screamnext, maxscream, int); } else { maxscream = pos + pos / 4; Renew(screamnext, maxscream, int); } } sfirst = screamfirst; snext = screamnext; if (!sfirst || !snext) fatal("do_study: out of memory"); for (ch = 256; ch; --ch) *sfirst++ = -1; sfirst -= 256; while (--pos >= 0) { ch = s[pos]; if (sfirst[ch] >= 0) snext[pos] = sfirst[ch] - pos; else snext[pos] = -pos; sfirst[ch] = pos; /* If there were any case insensitive searches, we must assume they * all are. This speeds up insensitive searches much more than * it slows down sensitive ones. */ if (sawi) sfirst[fold[ch]] = pos; } str->str_pok |= SP_STUDIED; retval = 1; ret: str_numset(arg->arg_ptr.arg_str,(double)retval); stack->ary_array[retarg] = arg->arg_ptr.arg_str; return retarg; } int /*SUPPRESS 590*/ do_defined(str,arg,gimme,arglast) STR *str; register ARG *arg; int gimme; int *arglast; { register int type; register int retarg = arglast[0] + 1; int retval; ARRAY *ary; HASH *hash; if ((arg[1].arg_type & A_MASK) != A_LEXPR) fatal("Illegal argument to defined()"); arg = arg[1].arg_ptr.arg_arg; type = arg->arg_type; if (type == O_SUBR || type == O_DBSUBR) { if ((arg[1].arg_type & A_MASK) == A_WORD) retval = stab_sub(arg[1].arg_ptr.arg_stab) != 0; else { STR *tmpstr = STAB_STR(arg[1].arg_ptr.arg_stab); retval = tmpstr && stab_sub(stabent(str_get(tmpstr),TRUE)) != 0; } } else if (type == O_ARRAY || type == O_LARRAY || type == O_ASLICE || type == O_LASLICE ) retval = ((ary = stab_xarray(arg[1].arg_ptr.arg_stab)) != 0 && ary->ary_max >= 0 ); else if (type == O_HASH || type == O_LHASH || type == O_HSLICE || type == O_LHSLICE ) retval = ((hash = stab_xhash(arg[1].arg_ptr.arg_stab)) != 0 && hash->tbl_array); else retval = FALSE; str_numset(str,(double)retval); stack->ary_array[retarg] = str; return retarg; } int /*SUPPRESS 590*/ do_undef(str,arg,gimme,arglast) STR *str; register ARG *arg; int gimme; int *arglast; { register int type; register STAB *stab; int retarg = arglast[0] + 1; if ((arg[1].arg_type & A_MASK) != A_LEXPR) fatal("Illegal argument to undef()"); arg = arg[1].arg_ptr.arg_arg; type = arg->arg_type; if (type == O_ARRAY || type == O_LARRAY) { stab = arg[1].arg_ptr.arg_stab; afree(stab_xarray(stab)); stab_xarray(stab) = anew(stab); /* so "@array" still works */ } else if (type == O_HASH || type == O_LHASH) { stab = arg[1].arg_ptr.arg_stab; if (stab == envstab) environ[0] = Nullch; else if (stab == sigstab) { int i; for (i = 1; i < NSIG; i++) signal(i, SIG_DFL); /* munch, munch, munch */ } (void)hfree(stab_xhash(stab), TRUE); stab_xhash(stab) = Null(HASH*); } else if (type == O_SUBR || type == O_DBSUBR) { stab = arg[1].arg_ptr.arg_stab; if ((arg[1].arg_type & A_MASK) != A_WORD) { STR *tmpstr = STAB_STR(arg[1].arg_ptr.arg_stab); if (tmpstr) stab = stabent(str_get(tmpstr),TRUE); else stab = Nullstab; } if (stab && stab_sub(stab)) { cmd_free(stab_sub(stab)->cmd); stab_sub(stab)->cmd = Nullcmd; afree(stab_sub(stab)->tosave); Safefree(stab_sub(stab)); stab_sub(stab) = Null(SUBR*); } } else fatal("Can't undefine that kind of object"); str_numset(str,0.0); stack->ary_array[retarg] = str; return retarg; } int do_vec(lvalue,astr,arglast) int lvalue; STR *astr; int *arglast; { STR **st = stack->ary_array; int sp = arglast[0]; register STR *str = st[++sp]; register int offset = (int)str_gnum(st[++sp]); register int size = (int)str_gnum(st[++sp]); unsigned char *s = (unsigned char*)str_get(str); unsigned long retnum; int len; sp = arglast[1]; offset *= size; /* turn into bit offset */ len = (offset + size + 7) / 8; if (offset < 0 || size < 1) retnum = 0; else if (!lvalue && len > str->str_cur) retnum = 0; else { if (len > str->str_cur) { STR_GROW(str,len); (void)memzero(str->str_ptr + str->str_cur, len - str->str_cur); str->str_cur = len; } s = (unsigned char*)str_get(str); if (size < 8) retnum = (s[offset >> 3] >> (offset & 7)) & ((1 << size) - 1); else { offset >>= 3; if (size == 8) retnum = s[offset]; else if (size == 16) retnum = ((unsigned long) s[offset] << 8) + s[offset+1]; else if (size == 32) retnum = ((unsigned long) s[offset] << 24) + ((unsigned long) s[offset + 1] << 16) + (s[offset + 2] << 8) + s[offset+3]; } if (lvalue) { /* it's an lvalue! */ struct lstring *lstr = (struct lstring*)astr; astr->str_magic = str; st[sp]->str_rare = 'v'; lstr->lstr_offset = offset; lstr->lstr_len = size; } } str_numset(astr,(double)retnum); st[sp] = astr; return sp; } void do_vecset(mstr,str) STR *mstr; STR *str; { struct lstring *lstr = (struct lstring*)str; register int offset; register int size; register unsigned char *s = (unsigned char*)mstr->str_ptr; register unsigned long lval = U_L(str_gnum(str)); int mask; mstr->str_rare = 0; str->str_magic = Nullstr; offset = lstr->lstr_offset; size = lstr->lstr_len; if (size < 8) { mask = (1 << size) - 1; size = offset & 7; lval &= mask; offset >>= 3; s[offset] &= ~(mask << size); s[offset] |= lval << size; } else { if (size == 8) s[offset] = lval & 255; else if (size == 16) { s[offset] = (lval >> 8) & 255; s[offset+1] = lval & 255; } else if (size == 32) { s[offset] = (lval >> 24) & 255; s[offset+1] = (lval >> 16) & 255; s[offset+2] = (lval >> 8) & 255; s[offset+3] = lval & 255; } } } void do_chop(astr,str) register STR *astr; register STR *str; { register char *tmps; register int i; ARRAY *ary; HASH *hash; HENT *entry; if (!str) return; if (str->str_state == SS_ARY) { ary = stab_array(str->str_u.str_stab); for (i = 0; i <= ary->ary_fill; i++) do_chop(astr,ary->ary_array[i]); return; } if (str->str_state == SS_HASH) { hash = stab_hash(str->str_u.str_stab); (void)hiterinit(hash); /*SUPPRESS 560*/ while (entry = hiternext(hash)) do_chop(astr,hiterval(hash,entry)); return; } tmps = str_get(str); if (tmps && str->str_cur) { tmps += str->str_cur - 1; str_nset(astr,tmps,1); /* remember last char */ *tmps = '\0'; /* wipe it out */ str->str_cur = tmps - str->str_ptr; str->str_nok = 0; STABSET(str); } else str_nset(astr,"",0); } void do_vop(optype,str,left,right) STR *str; STR *left; STR *right; { register char *s; register char *l = str_get(left); register char *r = str_get(right); register int len; len = left->str_cur; if (len > right->str_cur) len = right->str_cur; if (str->str_cur > len) str->str_cur = len; else if (str->str_cur < len) { STR_GROW(str,len); (void)memzero(str->str_ptr + str->str_cur, len - str->str_cur); str->str_cur = len; } str->str_pok = 1; str->str_nok = 0; s = str->str_ptr; if (!s) { str_nset(str,"",0); s = str->str_ptr; } switch (optype) { case O_BIT_AND: while (len--) *s++ = *l++ & *r++; break; case O_XOR: while (len--) *s++ = *l++ ^ *r++; goto mop_up; case O_BIT_OR: while (len--) *s++ = *l++ | *r++; mop_up: len = str->str_cur; if (right->str_cur > len) str_ncat(str,right->str_ptr+len,right->str_cur - len); else if (left->str_cur > len) str_ncat(str,left->str_ptr+len,left->str_cur - len); break; } } int do_syscall(arglast) int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register int items = arglast[2] - sp; #ifdef atarist unsigned long arg[14]; /* yes, we really need that many ! */ #else unsigned long arg[8]; #endif register int i = 0; int retval = -1; #ifdef HAS_SYSCALL #ifdef TAINT for (st += ++sp; items--; st++) tainted |= (*st)->str_tainted; st = stack->ary_array; sp = arglast[1]; items = arglast[2] - sp; #endif #ifdef TAINT taintproper("Insecure dependency in syscall"); #endif /* This probably won't work on machines where sizeof(long) != sizeof(int) * or where sizeof(long) != sizeof(char*). But such machines will * not likely have syscall implemented either, so who cares? */ while (items--) { if (st[++sp]->str_nok || !i) arg[i++] = (unsigned long)str_gnum(st[sp]); #ifndef lint else arg[i++] = (unsigned long)st[sp]->str_ptr; #endif /* lint */ } sp = arglast[1]; items = arglast[2] - sp; switch (items) { case 0: fatal("Too few args to syscall"); case 1: retval = syscall(arg[0]); break; case 2: retval = syscall(arg[0],arg[1]); break; case 3: retval = syscall(arg[0],arg[1],arg[2]); break; case 4: retval = syscall(arg[0],arg[1],arg[2],arg[3]); break; case 5: retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4]); break; case 6: retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]); break; case 7: retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]); break; case 8: retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6], arg[7]); break; #ifdef atarist case 9: retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6], arg[7], arg[8]); break; case 10: retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6], arg[7], arg[8], arg[9]); break; case 11: retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6], arg[7], arg[8], arg[9], arg[10]); break; case 12: retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6], arg[7], arg[8], arg[9], arg[10], arg[11]); break; case 13: retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6], arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]); break; case 14: retval = syscall(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6], arg[7], arg[8], arg[9], arg[10], arg[11], arg[12], arg[13]); break; #endif /* atarist */ } return retval; #else fatal("syscall() unimplemented"); #endif } Index: head/gnu/usr.bin/perl/perl/doio.c =================================================================== --- head/gnu/usr.bin/perl/perl/doio.c (revision 2652) +++ head/gnu/usr.bin/perl/perl/doio.c (revision 2653) @@ -1,2951 +1,2954 @@ -/* $RCSfile: doio.c,v $$Revision: 1.2 $$Date: 1994/03/09 22:24:27 $ +/* $RCSfile: doio.c,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:32 $ * * Copyright (c) 1991, Larry Wall * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. * * $Log: doio.c,v $ + * Revision 1.1.1.1 1994/09/10 06:27:32 gclarkii + * Initial import of Perl 4.046 bmaked + * * Revision 1.2 1994/03/09 22:24:27 ache * (cast) added for last argument of semctl * * Revision 1.1.1.1 1993/08/23 21:29:36 nate * PERL! * * Revision 4.0.1.6 92/06/11 21:08:16 lwall * patch34: some systems don't declare h_errno extern in header files * * Revision 4.0.1.5 92/06/08 13:00:21 lwall * patch20: some machines don't define ENOTSOCK in errno.h * patch20: new warnings for failed use of stat operators on filenames with \n * patch20: wait failed when STDOUT or STDERR reopened to a pipe * patch20: end of file latch not reset on reopen of STDIN * patch20: seek(HANDLE, 0, 1) went to eof because of ancient Ultrix workaround * patch20: fixed memory leak on system() for vfork() machines * patch20: get*by* routines now return something useful in a scalar context * patch20: h_errno now accessible via $? * * Revision 4.0.1.4 91/11/05 16:51:43 lwall * patch11: prepared for ctype implementations that don't define isascii() * patch11: perl mistook some streams for sockets because they return mode 0 too * patch11: reopening STDIN, STDOUT and STDERR failed on some machines * patch11: certain perl errors should set EBADF so that $! looks better * patch11: truncate on a closed filehandle could dump * patch11: stats of _ forgot whether prior stat was actually lstat * patch11: -T returned true on NFS directory * * Revision 4.0.1.3 91/06/10 01:21:19 lwall * patch10: read didn't work from character special files open for writing * patch10: close-on-exec wrongly set on system file descriptors * * Revision 4.0.1.2 91/06/07 10:53:39 lwall * patch4: new copyright notice * patch4: system fd's are now treated specially * patch4: added $^F variable to specify maximum system fd, default 2 * patch4: character special files now opened with bidirectional stdio buffers * patch4: taintchecks could improperly modify parent in vfork() * patch4: many, many itty-bitty portability fixes * * Revision 4.0.1.1 91/04/11 17:41:06 lwall * patch1: hopefully straightened out some of the Xenix mess * * Revision 4.0 91/03/20 01:07:06 lwall * 4.0 baseline. * */ #include "EXTERN.h" #include "perl.h" #include #include #include #ifdef HAS_SOCKET #include #include #ifndef ENOTSOCK #include #endif #endif #ifdef HAS_SELECT #ifdef I_SYS_SELECT #ifndef I_SYS_TIME #include #endif #endif #endif #ifdef HOST_NOT_FOUND extern int h_errno; #endif #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM) #include #ifdef HAS_MSG #include #endif #ifdef HAS_SEM #include #endif #ifdef HAS_SHM #include #endif #endif #ifdef I_PWD #include #endif #ifdef I_GRP #include #endif #ifdef I_UTIME #include #endif #ifdef I_FCNTL #include #endif #ifdef I_SYS_FILE #include #endif int laststatval = -1; int laststype = O_STAT; static char* warn_nl = "Unsuccessful %s on filename containing newline"; bool do_open(stab,name,len) STAB *stab; register char *name; int len; { FILE *fp; register STIO *stio = stab_io(stab); char *myname = savestr(name); int result; int fd; int writing = 0; char mode[3]; /* stdio file mode ("r\0" or "r+\0") */ FILE *saveifp = Nullfp; FILE *saveofp = Nullfp; char savetype = ' '; mode[0] = mode[1] = mode[2] = '\0'; name = myname; forkprocess = 1; /* assume true if no fork */ while (len && isSPACE(name[len-1])) name[--len] = '\0'; if (!stio) stio = stab_io(stab) = stio_new(); else if (stio->ifp) { fd = fileno(stio->ifp); if (stio->type == '-') result = 0; else if (fd <= maxsysfd) { saveifp = stio->ifp; saveofp = stio->ofp; savetype = stio->type; result = 0; } else if (stio->type == '|') result = mypclose(stio->ifp); else if (stio->ifp != stio->ofp) { if (stio->ofp) { result = fclose(stio->ofp); fclose(stio->ifp); /* clear stdio, fd already closed */ } else result = fclose(stio->ifp); } else result = fclose(stio->ifp); if (result == EOF && fd > maxsysfd) fprintf(stderr,"Warning: unable to close filehandle %s properly.\n", stab_ename(stab)); stio->ofp = stio->ifp = Nullfp; } if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */ mode[1] = *name++; mode[2] = '\0'; --len; writing = 1; } else { mode[1] = '\0'; } stio->type = *name; if (*name == '|') { /*SUPPRESS 530*/ for (name++; isSPACE(*name); name++) ; #ifdef TAINT taintenv(); taintproper("Insecure dependency in piped open"); #endif fp = mypopen(name,"w"); writing = 1; } else if (*name == '>') { #ifdef TAINT taintproper("Insecure dependency in open"); #endif name++; if (*name == '>') { mode[0] = stio->type = 'a'; name++; } else mode[0] = 'w'; writing = 1; if (*name == '&') { duplicity: name++; while (isSPACE(*name)) name++; if (isDIGIT(*name)) fd = atoi(name); else { stab = stabent(name,FALSE); if (!stab || !stab_io(stab)) { #ifdef EINVAL errno = EINVAL; #endif goto say_false; } if (stab_io(stab) && stab_io(stab)->ifp) { fd = fileno(stab_io(stab)->ifp); if (stab_io(stab)->type == 's') stio->type = 's'; } else fd = -1; } if (!(fp = fdopen(fd = dup(fd),mode))) { close(fd); } } else { while (isSPACE(*name)) name++; if (strEQ(name,"-")) { fp = stdout; stio->type = '-'; } else { fp = fopen(name,mode); } } } else { if (*name == '<') { mode[0] = 'r'; name++; while (isSPACE(*name)) name++; if (*name == '&') goto duplicity; if (strEQ(name,"-")) { fp = stdin; stio->type = '-'; } else fp = fopen(name,mode); } else if (name[len-1] == '|') { #ifdef TAINT taintenv(); taintproper("Insecure dependency in piped open"); #endif name[--len] = '\0'; while (len && isSPACE(name[len-1])) name[--len] = '\0'; /*SUPPRESS 530*/ for (; isSPACE(*name); name++) ; fp = mypopen(name,"r"); stio->type = '|'; } else { stio->type = '<'; /*SUPPRESS 530*/ for (; isSPACE(*name); name++) ; if (strEQ(name,"-")) { fp = stdin; stio->type = '-'; } else fp = fopen(name,"r"); } } if (!fp) { if (dowarn && stio->type == '<' && index(name, '\n')) warn(warn_nl, "open"); Safefree(myname); goto say_false; } Safefree(myname); if (stio->type && stio->type != '|' && stio->type != '-') { if (fstat(fileno(fp),&statbuf) < 0) { (void)fclose(fp); goto say_false; } if (S_ISSOCK(statbuf.st_mode)) stio->type = 's'; /* in case a socket was passed in to us */ #ifdef HAS_SOCKET else if ( #ifdef S_IFMT !(statbuf.st_mode & S_IFMT) #else !statbuf.st_mode #endif ) { int buflen = sizeof tokenbuf; - if (getsockname(fileno(fp), tokenbuf, &buflen) >= 0 + if (getsockname(fileno(fp), (struct sockaddr * )tokenbuf, &buflen) >= 0 || errno != ENOTSOCK) stio->type = 's'; /* some OS's return 0 on fstat()ed socket */ /* but some return 0 for streams too, sigh */ } #endif } if (saveifp) { /* must use old fp? */ fd = fileno(saveifp); if (saveofp) { fflush(saveofp); /* emulate fclose() */ if (saveofp != saveifp) { /* was a socket? */ fclose(saveofp); if (fd > 2) Safefree(saveofp); } } if (fd != fileno(fp)) { int pid; STR *str; dup2(fileno(fp), fd); str = afetch(fdpid,fileno(fp),TRUE); pid = str->str_u.str_useful; str->str_u.str_useful = 0; str = afetch(fdpid,fd,TRUE); str->str_u.str_useful = pid; fclose(fp); } fp = saveifp; clearerr(fp); } #if defined(HAS_FCNTL) && defined(F_SETFD) fd = fileno(fp); fcntl(fd,F_SETFD,fd > maxsysfd); #endif stio->ifp = fp; if (writing) { if (stio->type == 's' || (stio->type == '>' && S_ISCHR(statbuf.st_mode)) ) { if (!(stio->ofp = fdopen(fileno(fp),"w"))) { fclose(fp); stio->ifp = Nullfp; goto say_false; } } else stio->ofp = fp; } return TRUE; say_false: stio->ifp = saveifp; stio->ofp = saveofp; stio->type = savetype; return FALSE; } FILE * nextargv(stab) register STAB *stab; { register STR *str; #ifndef FLEXFILENAMES int filedev; int fileino; #endif int fileuid; int filegid; static int filemode = 0; static int lastfd; static char *oldname; if (!argvoutstab) argvoutstab = stabent("ARGVOUT",TRUE); if (filemode & (S_ISUID|S_ISGID)) { fflush(stab_io(argvoutstab)->ifp); /* chmod must follow last write */ #ifdef HAS_FCHMOD (void)fchmod(lastfd,filemode); #else (void)chmod(oldname,filemode); #endif } filemode = 0; while (alen(stab_xarray(stab)) >= 0) { str = ashift(stab_xarray(stab)); str_sset(stab_val(stab),str); STABSET(stab_val(stab)); oldname = str_get(stab_val(stab)); if (do_open(stab,oldname,stab_val(stab)->str_cur)) { if (inplace) { #ifdef TAINT taintproper("Insecure dependency in inplace open"); #endif if (strEQ(oldname,"-")) { str_free(str); defoutstab = stabent("STDOUT",TRUE); return stab_io(stab)->ifp; } #ifndef FLEXFILENAMES filedev = statbuf.st_dev; fileino = statbuf.st_ino; #endif filemode = statbuf.st_mode; fileuid = statbuf.st_uid; filegid = statbuf.st_gid; if (!S_ISREG(filemode)) { warn("Can't do inplace edit: %s is not a regular file", oldname ); do_close(stab,FALSE); str_free(str); continue; } if (*inplace) { #ifdef SUFFIX add_suffix(str,inplace); #else str_cat(str,inplace); #endif #ifndef FLEXFILENAMES if (stat(str->str_ptr,&statbuf) >= 0 && statbuf.st_dev == filedev && statbuf.st_ino == fileino ) { warn("Can't do inplace edit: %s > 14 characters", str->str_ptr ); do_close(stab,FALSE); str_free(str); continue; } #endif #ifdef HAS_RENAME #ifndef DOSISH if (rename(oldname,str->str_ptr) < 0) { warn("Can't rename %s to %s: %s, skipping file", oldname, str->str_ptr, strerror(errno) ); do_close(stab,FALSE); str_free(str); continue; } #else do_close(stab,FALSE); (void)unlink(str->str_ptr); (void)rename(oldname,str->str_ptr); do_open(stab,str->str_ptr,stab_val(stab)->str_cur); #endif /* MSDOS */ #else (void)UNLINK(str->str_ptr); if (link(oldname,str->str_ptr) < 0) { warn("Can't rename %s to %s: %s, skipping file", oldname, str->str_ptr, strerror(errno) ); do_close(stab,FALSE); str_free(str); continue; } (void)UNLINK(oldname); #endif } else { #ifndef DOSISH if (UNLINK(oldname) < 0) { warn("Can't rename %s to %s: %s, skipping file", oldname, str->str_ptr, strerror(errno) ); do_close(stab,FALSE); str_free(str); continue; } #else fatal("Can't do inplace edit without backup"); #endif } str_nset(str,">",1); str_cat(str,oldname); errno = 0; /* in case sprintf set errno */ if (!do_open(argvoutstab,str->str_ptr,str->str_cur)) { warn("Can't do inplace edit on %s: %s", oldname, strerror(errno) ); do_close(stab,FALSE); str_free(str); continue; } defoutstab = argvoutstab; lastfd = fileno(stab_io(argvoutstab)->ifp); (void)fstat(lastfd,&statbuf); #ifdef HAS_FCHMOD (void)fchmod(lastfd,filemode); #else (void)chmod(oldname,filemode); #endif if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) { #ifdef HAS_FCHOWN (void)fchown(lastfd,fileuid,filegid); #else #ifdef HAS_CHOWN (void)chown(oldname,fileuid,filegid); #endif #endif } } str_free(str); return stab_io(stab)->ifp; } else fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno)); str_free(str); } if (inplace) { (void)do_close(argvoutstab,FALSE); defoutstab = stabent("STDOUT",TRUE); } return Nullfp; } #ifdef HAS_PIPE void do_pipe(str, rstab, wstab) STR *str; STAB *rstab; STAB *wstab; { register STIO *rstio; register STIO *wstio; int fd[2]; if (!rstab) goto badexit; if (!wstab) goto badexit; rstio = stab_io(rstab); wstio = stab_io(wstab); if (!rstio) rstio = stab_io(rstab) = stio_new(); else if (rstio->ifp) do_close(rstab,FALSE); if (!wstio) wstio = stab_io(wstab) = stio_new(); else if (wstio->ifp) do_close(wstab,FALSE); if (pipe(fd) < 0) goto badexit; rstio->ifp = fdopen(fd[0], "r"); wstio->ofp = fdopen(fd[1], "w"); wstio->ifp = wstio->ofp; rstio->type = '<'; wstio->type = '>'; if (!rstio->ifp || !wstio->ofp) { if (rstio->ifp) fclose(rstio->ifp); else close(fd[0]); if (wstio->ofp) fclose(wstio->ofp); else close(fd[1]); goto badexit; } str_sset(str,&str_yes); return; badexit: str_sset(str,&str_undef); return; } #endif bool do_close(stab,explicit) STAB *stab; bool explicit; { bool retval = FALSE; register STIO *stio; int status; if (!stab) stab = argvstab; if (!stab) { errno = EBADF; return FALSE; } stio = stab_io(stab); if (!stio) { /* never opened */ if (dowarn && explicit) warn("Close on unopened file <%s>",stab_ename(stab)); return FALSE; } if (stio->ifp) { if (stio->type == '|') { status = mypclose(stio->ifp); retval = (status == 0); statusvalue = (unsigned short)status & 0xffff; } else if (stio->type == '-') retval = TRUE; else { if (stio->ofp && stio->ofp != stio->ifp) { /* a socket */ retval = (fclose(stio->ofp) != EOF); fclose(stio->ifp); /* clear stdio, fd already closed */ } else retval = (fclose(stio->ifp) != EOF); } stio->ofp = stio->ifp = Nullfp; } if (explicit) stio->lines = 0; stio->type = ' '; return retval; } bool do_eof(stab) STAB *stab; { register STIO *stio; int ch; if (!stab) { /* eof() */ if (argvstab) stio = stab_io(argvstab); else return TRUE; } else stio = stab_io(stab); if (!stio) return TRUE; while (stio->ifp) { #ifdef STDSTDIO /* (the code works without this) */ if (stio->ifp->_cnt > 0) /* cheat a little, since */ return FALSE; /* this is the most usual case */ #endif ch = getc(stio->ifp); if (ch != EOF) { (void)ungetc(ch, stio->ifp); return FALSE; } #ifdef STDSTDIO if (stio->ifp->_cnt < -1) stio->ifp->_cnt = -1; #endif if (!stab) { /* not necessarily a real EOF yet? */ if (!nextargv(argvstab)) /* get another fp handy */ return TRUE; } else return TRUE; /* normal fp, definitely end of file */ } return TRUE; } long do_tell(stab) STAB *stab; { register STIO *stio; if (!stab) goto phooey; stio = stab_io(stab); if (!stio || !stio->ifp) goto phooey; #ifdef ULTRIX_STDIO_BOTCH if (feof(stio->ifp)) (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */ #endif return ftell(stio->ifp); phooey: if (dowarn) warn("tell() on unopened file"); errno = EBADF; return -1L; } bool do_seek(stab, pos, whence) STAB *stab; long pos; int whence; { register STIO *stio; if (!stab) goto nuts; stio = stab_io(stab); if (!stio || !stio->ifp) goto nuts; #ifdef ULTRIX_STDIO_BOTCH if (feof(stio->ifp)) (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */ #endif return fseek(stio->ifp, pos, whence) >= 0; nuts: if (dowarn) warn("seek() on unopened file"); errno = EBADF; return FALSE; } int do_ctl(optype,stab,func,argstr) int optype; STAB *stab; int func; STR *argstr; { register STIO *stio; register char *s; int retval; if (!stab || !argstr || !(stio = stab_io(stab)) || !stio->ifp) { errno = EBADF; /* well, sort of... */ return -1; } if (argstr->str_pok || !argstr->str_nok) { if (!argstr->str_pok) s = str_get(argstr); #ifdef IOCPARM_MASK #ifndef IOCPARM_LEN #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK) #endif #endif #ifdef IOCPARM_LEN retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */ #else retval = 256; /* otherwise guess at what's safe */ #endif if (argstr->str_cur < retval) { Str_Grow(argstr,retval+1); argstr->str_cur = retval; } s = argstr->str_ptr; s[argstr->str_cur] = 17; /* a little sanity check here */ } else { retval = (int)str_gnum(argstr); #ifdef DOSISH s = (char*)(long)retval; /* ouch */ #else s = (char*)retval; /* ouch */ #endif } #ifndef lint if (optype == O_IOCTL) retval = ioctl(fileno(stio->ifp), func, s); else #ifdef DOSISH fatal("fcntl is not implemented"); #else #ifdef HAS_FCNTL retval = fcntl(fileno(stio->ifp), func, s); #else fatal("fcntl is not implemented"); #endif #endif #else /* lint */ retval = 0; #endif /* lint */ if (argstr->str_pok) { if (s[argstr->str_cur] != 17) fatal("Return value overflowed string"); s[argstr->str_cur] = 0; /* put our null back */ } return retval; } int do_stat(str,arg,gimme,arglast) STR *str; register ARG *arg; int gimme; int *arglast; { register ARRAY *ary = stack; register int sp = arglast[0] + 1; int max = 13; if ((arg[1].arg_type & A_MASK) == A_WORD) { tmpstab = arg[1].arg_ptr.arg_stab; if (tmpstab != defstab) { laststype = O_STAT; statstab = tmpstab; str_set(statname,""); if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp || fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) { max = 0; laststatval = -1; } } else if (laststatval < 0) max = 0; } else { str_set(statname,str_get(ary->ary_array[sp])); statstab = Nullstab; #ifdef HAS_LSTAT laststype = arg->arg_type; if (arg->arg_type == O_LSTAT) laststatval = lstat(str_get(statname),&statcache); else #endif laststatval = stat(str_get(statname),&statcache); if (laststatval < 0) { if (dowarn && index(str_get(statname), '\n')) warn(warn_nl, "stat"); max = 0; } } if (gimme != G_ARRAY) { if (max) str_sset(str,&str_yes); else str_sset(str,&str_undef); STABSET(str); ary->ary_array[sp] = str; return sp; } sp--; if (max) { #ifndef lint (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_dev))); (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_ino))); (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_mode))); (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_nlink))); (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_uid))); (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_gid))); (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_rdev))); (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_size))); (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_atime))); (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_mtime))); (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_ctime))); #ifdef STATBLOCKS (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_blksize))); (void)astore(ary,++sp, str_2mortal(str_nmake((double)statcache.st_blocks))); #else (void)astore(ary,++sp, str_2mortal(str_make("",0))); (void)astore(ary,++sp, str_2mortal(str_make("",0))); #endif #else /* lint */ (void)astore(ary,++sp,str_nmake(0.0)); #endif /* lint */ } return sp; } #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP) /* code courtesy of William Kucharski */ #define HAS_CHSIZE int chsize(fd, length) int fd; /* file descriptor */ off_t length; /* length to set file to */ { extern long lseek(); struct flock fl; struct stat filebuf; if (fstat(fd, &filebuf) < 0) return -1; if (filebuf.st_size < length) { /* extend file length */ if ((lseek(fd, (length - 1), 0)) < 0) return -1; /* write a "0" byte */ if ((write(fd, "", 1)) != 1) return -1; } else { /* truncate length */ fl.l_whence = 0; fl.l_len = 0; fl.l_start = length; fl.l_type = F_WRLCK; /* write lock on file space */ /* * This relies on the UNDOCUMENTED F_FREESP argument to * fcntl(2), which truncates the file so that it ends at the * position indicated by fl.l_start. * * Will minor miracles never cease? */ if (fcntl(fd, F_FREESP, &fl) < 0) return -1; } return 0; } #endif /* F_FREESP */ int /*SUPPRESS 590*/ do_truncate(str,arg,gimme,arglast) STR *str; register ARG *arg; int gimme; int *arglast; { register ARRAY *ary = stack; register int sp = arglast[0] + 1; off_t len = (off_t)str_gnum(ary->ary_array[sp+1]); int result = 1; STAB *tmpstab; #if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE) #ifdef HAS_TRUNCATE if ((arg[1].arg_type & A_MASK) == A_WORD) { tmpstab = arg[1].arg_ptr.arg_stab; if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp || ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0) result = 0; } else if (truncate(str_get(ary->ary_array[sp]), len) < 0) result = 0; #else if ((arg[1].arg_type & A_MASK) == A_WORD) { tmpstab = arg[1].arg_ptr.arg_stab; if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp || chsize(fileno(stab_io(tmpstab)->ifp), len) < 0) result = 0; } else { int tmpfd; if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0) result = 0; else { if (chsize(tmpfd, len) < 0) result = 0; close(tmpfd); } } #endif if (result) str_sset(str,&str_yes); else str_sset(str,&str_undef); STABSET(str); ary->ary_array[sp] = str; return sp; #else fatal("truncate not implemented"); #endif } int looks_like_number(str) STR *str; { register char *s; register char *send; if (!str->str_pok) return TRUE; s = str->str_ptr; send = s + str->str_cur; while (isSPACE(*s)) s++; if (s >= send) return FALSE; if (*s == '+' || *s == '-') s++; while (isDIGIT(*s)) s++; if (s == send) return TRUE; if (*s == '.') s++; else if (s == str->str_ptr) return FALSE; while (isDIGIT(*s)) s++; if (s == send) return TRUE; if (*s == 'e' || *s == 'E') { s++; if (*s == '+' || *s == '-') s++; while (isDIGIT(*s)) s++; } while (isSPACE(*s)) s++; if (s >= send) return TRUE; return FALSE; } bool do_print(str,fp) register STR *str; FILE *fp; { register char *tmps; if (!fp) { if (dowarn) warn("print to unopened file"); errno = EBADF; return FALSE; } if (!str) return TRUE; if (ofmt && ((str->str_nok && str->str_u.str_nval != 0.0) || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) { fprintf(fp, ofmt, str->str_u.str_nval); return !ferror(fp); } else { tmps = str_get(str); if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0' && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) { STR *tmpstr = str_mortal(&str_undef); stab_efullname(tmpstr,((STAB*)str));/* a stab value, be nice */ str = tmpstr; tmps = str->str_ptr; putc('*',fp); } if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp))) return FALSE; } return TRUE; } bool do_aprint(arg,fp,arglast) register ARG *arg; register FILE *fp; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register int retval; register int items = arglast[2] - sp; if (!fp) { if (dowarn) warn("print to unopened file"); errno = EBADF; return FALSE; } st += ++sp; if (arg->arg_type == O_PRTF) { do_sprintf(arg->arg_ptr.arg_str,items,st); retval = do_print(arg->arg_ptr.arg_str,fp); } else { retval = (items <= 0); for (; items > 0; items--,st++) { if (retval && ofslen) { if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) { retval = FALSE; break; } } if (!(retval = do_print(*st, fp))) break; } if (retval && orslen) if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp)) retval = FALSE; } return retval; } int mystat(arg,str) ARG *arg; STR *str; { STIO *stio; if (arg[1].arg_type & A_DONT) { stio = stab_io(arg[1].arg_ptr.arg_stab); if (stio && stio->ifp) { statstab = arg[1].arg_ptr.arg_stab; str_set(statname,""); laststype = O_STAT; return (laststatval = fstat(fileno(stio->ifp), &statcache)); } else { if (arg[1].arg_ptr.arg_stab == defstab) return laststatval; if (dowarn) warn("Stat on unopened file <%s>", stab_ename(arg[1].arg_ptr.arg_stab)); statstab = Nullstab; str_set(statname,""); return (laststatval = -1); } } else { statstab = Nullstab; str_set(statname,str_get(str)); laststype = O_STAT; laststatval = stat(str_get(str),&statcache); if (laststatval < 0 && dowarn && index(str_get(str), '\n')) warn(warn_nl, "stat"); return laststatval; } } int mylstat(arg,str) ARG *arg; STR *str; { if (arg[1].arg_type & A_DONT) { if (arg[1].arg_ptr.arg_stab == defstab) { if (laststype != O_LSTAT) fatal("The stat preceding -l _ wasn't an lstat"); return laststatval; } fatal("You can't use -l on a filehandle"); } laststype = O_LSTAT; statstab = Nullstab; str_set(statname,str_get(str)); #ifdef HAS_LSTAT laststatval = lstat(str_get(str),&statcache); #else laststatval = stat(str_get(str),&statcache); #endif if (laststatval < 0 && dowarn && index(str_get(str), '\n')) warn(warn_nl, "lstat"); return laststatval; } STR * do_fttext(arg,str) register ARG *arg; STR *str; { int i; int len; int odd = 0; STDCHAR tbuf[512]; register STDCHAR *s; register STIO *stio; if (arg[1].arg_type & A_DONT) { if (arg[1].arg_ptr.arg_stab == defstab) { if (statstab) stio = stab_io(statstab); else { str = statname; goto really_filename; } } else { statstab = arg[1].arg_ptr.arg_stab; str_set(statname,""); stio = stab_io(statstab); } if (stio && stio->ifp) { #if defined(STDSTDIO) || defined(atarist) /* this will work with atariST */ fstat(fileno(stio->ifp),&statcache); if (S_ISDIR(statcache.st_mode)) /* handle NFS glitch */ return arg->arg_type == O_FTTEXT ? &str_no : &str_yes; if (stio->ifp->_cnt <= 0) { i = getc(stio->ifp); if (i != EOF) (void)ungetc(i,stio->ifp); } if (stio->ifp->_cnt <= 0) /* null file is anything */ return &str_yes; len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base); s = stio->ifp->_base; #else fatal("-T and -B not implemented on filehandles"); #endif } else { if (dowarn) warn("Test on unopened file <%s>", stab_ename(arg[1].arg_ptr.arg_stab)); errno = EBADF; return &str_undef; } } else { statstab = Nullstab; str_set(statname,str_get(str)); really_filename: i = open(str_get(str),0); if (i < 0) { if (dowarn && index(str_get(str), '\n')) warn(warn_nl, "open"); return &str_undef; } fstat(i,&statcache); len = read(i,tbuf,512); (void)close(i); if (len <= 0) { if (S_ISDIR(statcache.st_mode) && arg->arg_type == O_FTTEXT) return &str_no; /* special case NFS directories */ return &str_yes; /* null file is anything */ } s = tbuf; } /* now scan s to look for textiness */ for (i = 0; i < len; i++,s++) { if (!*s) { /* null never allowed in text */ odd += len; break; } else if (*s & 128) odd++; else if (*s < 32 && *s != '\n' && *s != '\r' && *s != '\b' && *s != '\t' && *s != '\f' && *s != 27) odd++; } if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */ return &str_no; else return &str_yes; } static char **Argv = Null(char **); static char *Cmd = Nullch; bool do_aexec(really,arglast) STR *really; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register int items = arglast[2] - sp; register char **a; char *tmps; if (items) { New(401,Argv, items+1, char*); a = Argv; for (st += ++sp; items > 0; items--,st++) { if (*st) *a++ = str_get(*st); else *a++ = ""; } *a = Nullch; #ifdef TAINT if (*Argv[0] != '/') /* will execvp use PATH? */ taintenv(); /* testing IFS here is overkill, probably */ #endif if (really && *(tmps = str_get(really))) execvp(tmps,Argv); else execvp(Argv[0],Argv); } do_execfree(); return FALSE; } void do_execfree() { if (Argv) { Safefree(Argv); Argv = Null(char **); } if (Cmd) { Safefree(Cmd); Cmd = Nullch; } } bool do_exec(cmd) char *cmd; { register char **a; register char *s; char flags[10]; /* save an extra exec if possible */ #ifdef CSH if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) { strcpy(flags,"-c"); s = cmd+cshlen+3; if (*s == 'f') { s++; strcat(flags,"f"); } if (*s == ' ') s++; if (*s++ == '\'') { char *ncmd = s; while (*s) s++; if (s[-1] == '\n') *--s = '\0'; if (s[-1] == '\'') { *--s = '\0'; execl(cshname,"csh", flags,ncmd,(char*)0); *s = '\''; return FALSE; } } } #endif /* CSH */ /* see if there are shell metacharacters in it */ /*SUPPRESS 530*/ for (s = cmd; *s && isALPHA(*s); s++) ; /* catch VAR=val gizmo */ if (*s == '=') goto doshell; for (s = cmd; *s; s++) { if (*s != ' ' && !isALPHA(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) { if (*s == '\n' && !s[1]) { *s = '\0'; break; } doshell: execl("/bin/sh","sh","-c",cmd,(char*)0); return FALSE; } } New(402,Argv, (s - cmd) / 2 + 2, char*); Cmd = nsavestr(cmd, s-cmd); a = Argv; for (s = Cmd; *s;) { while (*s && isSPACE(*s)) s++; if (*s) *(a++) = s; while (*s && !isSPACE(*s)) s++; if (*s) *s++ = '\0'; } *a = Nullch; if (Argv[0]) { execvp(Argv[0],Argv); if (errno == ENOEXEC) { /* for system V NIH syndrome */ do_execfree(); goto doshell; } } do_execfree(); return FALSE; } #ifdef HAS_SOCKET int do_socket(stab, arglast) STAB *stab; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register STIO *stio; int domain, type, protocol, fd; if (!stab) { errno = EBADF; return FALSE; } stio = stab_io(stab); if (!stio) stio = stab_io(stab) = stio_new(); else if (stio->ifp) do_close(stab,FALSE); domain = (int)str_gnum(st[++sp]); type = (int)str_gnum(st[++sp]); protocol = (int)str_gnum(st[++sp]); #ifdef TAINT taintproper("Insecure dependency in socket"); #endif fd = socket(domain,type,protocol); if (fd < 0) return FALSE; stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */ stio->ofp = fdopen(fd, "w"); stio->type = 's'; if (!stio->ifp || !stio->ofp) { if (stio->ifp) fclose(stio->ifp); if (stio->ofp) fclose(stio->ofp); if (!stio->ifp && !stio->ofp) close(fd); return FALSE; } return TRUE; } int do_bind(stab, arglast) STAB *stab; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register STIO *stio; char *addr; if (!stab) goto nuts; stio = stab_io(stab); if (!stio || !stio->ifp) goto nuts; addr = str_get(st[++sp]); #ifdef TAINT taintproper("Insecure dependency in bind"); #endif - return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0; + return bind(fileno(stio->ifp), (struct sockaddr * ) addr, st[sp]->str_cur) >= 0; nuts: if (dowarn) warn("bind() on closed fd"); errno = EBADF; return FALSE; } int do_connect(stab, arglast) STAB *stab; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register STIO *stio; char *addr; if (!stab) goto nuts; stio = stab_io(stab); if (!stio || !stio->ifp) goto nuts; addr = str_get(st[++sp]); #ifdef TAINT taintproper("Insecure dependency in connect"); #endif - return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0; + return connect(fileno(stio->ifp), (struct sockaddr *) addr, st[sp]->str_cur) >= 0; nuts: if (dowarn) warn("connect() on closed fd"); errno = EBADF; return FALSE; } int do_listen(stab, arglast) STAB *stab; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register STIO *stio; int backlog; if (!stab) goto nuts; stio = stab_io(stab); if (!stio || !stio->ifp) goto nuts; backlog = (int)str_gnum(st[++sp]); return listen(fileno(stio->ifp), backlog) >= 0; nuts: if (dowarn) warn("listen() on closed fd"); errno = EBADF; return FALSE; } void do_accept(str, nstab, gstab) STR *str; STAB *nstab; STAB *gstab; { register STIO *nstio; register STIO *gstio; int len = sizeof buf; int fd; if (!nstab) goto badexit; if (!gstab) goto nuts; gstio = stab_io(gstab); nstio = stab_io(nstab); if (!gstio || !gstio->ifp) goto nuts; if (!nstio) nstio = stab_io(nstab) = stio_new(); else if (nstio->ifp) do_close(nstab,FALSE); fd = accept(fileno(gstio->ifp),(struct sockaddr *)buf,&len); if (fd < 0) goto badexit; nstio->ifp = fdopen(fd, "r"); nstio->ofp = fdopen(fd, "w"); nstio->type = 's'; if (!nstio->ifp || !nstio->ofp) { if (nstio->ifp) fclose(nstio->ifp); if (nstio->ofp) fclose(nstio->ofp); if (!nstio->ifp && !nstio->ofp) close(fd); goto badexit; } str_nset(str, buf, len); return; nuts: if (dowarn) warn("accept() on closed fd"); errno = EBADF; badexit: str_sset(str,&str_undef); return; } int do_shutdown(stab, arglast) STAB *stab; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register STIO *stio; int how; if (!stab) goto nuts; stio = stab_io(stab); if (!stio || !stio->ifp) goto nuts; how = (int)str_gnum(st[++sp]); return shutdown(fileno(stio->ifp), how) >= 0; nuts: if (dowarn) warn("shutdown() on closed fd"); errno = EBADF; return FALSE; } int do_sopt(optype, stab, arglast) int optype; STAB *stab; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register STIO *stio; int fd; unsigned int lvl; unsigned int optname; if (!stab) goto nuts; stio = stab_io(stab); if (!stio || !stio->ifp) goto nuts; fd = fileno(stio->ifp); lvl = (unsigned int)str_gnum(st[sp+1]); optname = (unsigned int)str_gnum(st[sp+2]); switch (optype) { case O_GSOCKOPT: st[sp] = str_2mortal(Str_new(22,257)); st[sp]->str_cur = 256; st[sp]->str_pok = 1; if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, (int*)&st[sp]->str_cur) < 0) goto nuts; break; case O_SSOCKOPT: st[sp] = st[sp+3]; if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0) goto nuts; st[sp] = &str_yes; break; } return sp; nuts: if (dowarn) warn("[gs]etsockopt() on closed fd"); st[sp] = &str_undef; errno = EBADF; return sp; } int do_getsockname(optype, stab, arglast) int optype; STAB *stab; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register STIO *stio; int fd; if (!stab) goto nuts; stio = stab_io(stab); if (!stio || !stio->ifp) goto nuts; st[sp] = str_2mortal(Str_new(22,257)); st[sp]->str_cur = 256; st[sp]->str_pok = 1; fd = fileno(stio->ifp); switch (optype) { case O_GETSOCKNAME: - if (getsockname(fd, st[sp]->str_ptr, (int*)&st[sp]->str_cur) < 0) + if (getsockname(fd, (struct sockaddr *) st[sp]->str_ptr, (int*)&st[sp]->str_cur) < 0) goto nuts2; break; case O_GETPEERNAME: - if (getpeername(fd, st[sp]->str_ptr, (int*)&st[sp]->str_cur) < 0) + if (getpeername(fd, (struct sockaddr *) st[sp]->str_ptr, (int*)&st[sp]->str_cur) < 0) goto nuts2; break; } return sp; nuts: if (dowarn) warn("get{sock,peer}name() on closed fd"); errno = EBADF; nuts2: st[sp] = &str_undef; return sp; } int do_ghent(which,gimme,arglast) int which; int gimme; int *arglast; { register ARRAY *ary = stack; register int sp = arglast[0]; register char **elem; register STR *str; struct hostent *gethostbyname(); struct hostent *gethostbyaddr(); #ifdef HAS_GETHOSTENT struct hostent *gethostent(); #endif struct hostent *hent; unsigned long len; if (which == O_GHBYNAME) { char *name = str_get(ary->ary_array[sp+1]); hent = gethostbyname(name); } else if (which == O_GHBYADDR) { STR *addrstr = ary->ary_array[sp+1]; int addrtype = (int)str_gnum(ary->ary_array[sp+2]); char *addr = str_get(addrstr); hent = gethostbyaddr(addr,addrstr->str_cur,addrtype); } else #ifdef HAS_GETHOSTENT hent = gethostent(); #else fatal("gethostent not implemented"); #endif #ifdef HOST_NOT_FOUND if (!hent) statusvalue = (unsigned short)h_errno & 0xffff; #endif if (gimme != G_ARRAY) { astore(ary, ++sp, str = str_mortal(&str_undef)); if (hent) { if (which == O_GHBYNAME) { #ifdef h_addr str_nset(str, *hent->h_addr, hent->h_length); #else str_nset(str, hent->h_addr, hent->h_length); #endif } else str_set(str, hent->h_name); } return sp; } if (hent) { #ifndef lint (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_set(str, hent->h_name); (void)astore(ary, ++sp, str = str_mortal(&str_no)); for (elem = hent->h_aliases; *elem; elem++) { str_cat(str, *elem); if (elem[1]) str_ncat(str," ",1); } (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_numset(str, (double)hent->h_addrtype); (void)astore(ary, ++sp, str = str_mortal(&str_no)); len = hent->h_length; str_numset(str, (double)len); #ifdef h_addr for (elem = hent->h_addr_list; *elem; elem++) { (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_nset(str, *elem, len); } #else (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_nset(str, hent->h_addr, len); #endif /* h_addr */ #else /* lint */ elem = Nullch; elem = elem; (void)astore(ary, ++sp, str_mortal(&str_no)); #endif /* lint */ } return sp; } int do_gnent(which,gimme,arglast) int which; int gimme; int *arglast; { register ARRAY *ary = stack; register int sp = arglast[0]; register char **elem; register STR *str; struct netent *getnetbyname(); struct netent *getnetbyaddr(); struct netent *getnetent(); struct netent *nent; if (which == O_GNBYNAME) { char *name = str_get(ary->ary_array[sp+1]); nent = getnetbyname(name); } else if (which == O_GNBYADDR) { unsigned long addr = U_L(str_gnum(ary->ary_array[sp+1])); int addrtype = (int)str_gnum(ary->ary_array[sp+2]); nent = getnetbyaddr((long)addr,addrtype); } else nent = getnetent(); if (gimme != G_ARRAY) { astore(ary, ++sp, str = str_mortal(&str_undef)); if (nent) { if (which == O_GNBYNAME) str_numset(str, (double)nent->n_net); else str_set(str, nent->n_name); } return sp; } if (nent) { #ifndef lint (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_set(str, nent->n_name); (void)astore(ary, ++sp, str = str_mortal(&str_no)); for (elem = nent->n_aliases; *elem; elem++) { str_cat(str, *elem); if (elem[1]) str_ncat(str," ",1); } (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_numset(str, (double)nent->n_addrtype); (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_numset(str, (double)nent->n_net); #else /* lint */ elem = Nullch; elem = elem; (void)astore(ary, ++sp, str_mortal(&str_no)); #endif /* lint */ } return sp; } int do_gpent(which,gimme,arglast) int which; int gimme; int *arglast; { register ARRAY *ary = stack; register int sp = arglast[0]; register char **elem; register STR *str; struct protoent *getprotobyname(); struct protoent *getprotobynumber(); struct protoent *getprotoent(); struct protoent *pent; if (which == O_GPBYNAME) { char *name = str_get(ary->ary_array[sp+1]); pent = getprotobyname(name); } else if (which == O_GPBYNUMBER) { int proto = (int)str_gnum(ary->ary_array[sp+1]); pent = getprotobynumber(proto); } else pent = getprotoent(); if (gimme != G_ARRAY) { astore(ary, ++sp, str = str_mortal(&str_undef)); if (pent) { if (which == O_GPBYNAME) str_numset(str, (double)pent->p_proto); else str_set(str, pent->p_name); } return sp; } if (pent) { #ifndef lint (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_set(str, pent->p_name); (void)astore(ary, ++sp, str = str_mortal(&str_no)); for (elem = pent->p_aliases; *elem; elem++) { str_cat(str, *elem); if (elem[1]) str_ncat(str," ",1); } (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_numset(str, (double)pent->p_proto); #else /* lint */ elem = Nullch; elem = elem; (void)astore(ary, ++sp, str_mortal(&str_no)); #endif /* lint */ } return sp; } int do_gsent(which,gimme,arglast) int which; int gimme; int *arglast; { register ARRAY *ary = stack; register int sp = arglast[0]; register char **elem; register STR *str; struct servent *getservbyname(); struct servent *getservbynumber(); struct servent *getservent(); struct servent *sent; if (which == O_GSBYNAME) { char *name = str_get(ary->ary_array[sp+1]); char *proto = str_get(ary->ary_array[sp+2]); if (proto && !*proto) proto = Nullch; sent = getservbyname(name,proto); } else if (which == O_GSBYPORT) { int port = (int)str_gnum(ary->ary_array[sp+1]); char *proto = str_get(ary->ary_array[sp+2]); sent = getservbyport(port,proto); } else sent = getservent(); if (gimme != G_ARRAY) { astore(ary, ++sp, str = str_mortal(&str_undef)); if (sent) { if (which == O_GSBYNAME) { #ifdef HAS_NTOHS str_numset(str, (double)ntohs(sent->s_port)); #else str_numset(str, (double)(sent->s_port)); #endif } else str_set(str, sent->s_name); } return sp; } if (sent) { #ifndef lint (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_set(str, sent->s_name); (void)astore(ary, ++sp, str = str_mortal(&str_no)); for (elem = sent->s_aliases; *elem; elem++) { str_cat(str, *elem); if (elem[1]) str_ncat(str," ",1); } (void)astore(ary, ++sp, str = str_mortal(&str_no)); #ifdef HAS_NTOHS str_numset(str, (double)ntohs(sent->s_port)); #else str_numset(str, (double)(sent->s_port)); #endif (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_set(str, sent->s_proto); #else /* lint */ elem = Nullch; elem = elem; (void)astore(ary, ++sp, str_mortal(&str_no)); #endif /* lint */ } return sp; } #endif /* HAS_SOCKET */ #ifdef HAS_SELECT int do_select(gimme,arglast) int gimme; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[0]; register int i; register int j; register char *s; register STR *str; double value; int maxlen = 0; int nfound; struct timeval timebuf; struct timeval *tbuf = &timebuf; int growsize; #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678 int masksize; int offset; char *fd_sets[4]; int k; #if BYTEORDER & 0xf0000 #define ORDERBYTE (0x88888888 - BYTEORDER) #else #define ORDERBYTE (0x4444 - BYTEORDER) #endif #endif for (i = 1; i <= 3; i++) { j = st[sp+i]->str_cur; if (maxlen < j) maxlen = j; } #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678 growsize = maxlen; /* little endians can use vecs directly */ #else #ifdef NFDBITS #ifndef NBBY #define NBBY 8 #endif masksize = NFDBITS / NBBY; #else masksize = sizeof(long); /* documented int, everyone seems to use long */ #endif growsize = maxlen + (masksize - (maxlen % masksize)); Zero(&fd_sets[0], 4, char*); #endif for (i = 1; i <= 3; i++) { str = st[sp+i]; j = str->str_len; if (j < growsize) { if (str->str_pok) { Str_Grow(str,growsize); s = str_get(str) + j; while (++j <= growsize) { *s++ = '\0'; } } else if (str->str_ptr) { Safefree(str->str_ptr); str->str_ptr = Nullch; } } #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678 s = str->str_ptr; if (s) { New(403, fd_sets[i], growsize, char); for (offset = 0; offset < growsize; offset += masksize) { for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4)) fd_sets[i][j+offset] = s[(k % masksize) + offset]; } } #endif } str = st[sp+4]; if (str->str_nok || str->str_pok) { value = str_gnum(str); if (value < 0.0) value = 0.0; timebuf.tv_sec = (long)value; value -= (double)timebuf.tv_sec; timebuf.tv_usec = (long)(value * 1000000.0); } else tbuf = Null(struct timeval*); #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678 nfound = select( maxlen * 8, - st[sp+1]->str_ptr, - st[sp+2]->str_ptr, - st[sp+3]->str_ptr, + (fd_set *) st[sp+1]->str_ptr, + (fd_set *) st[sp+2]->str_ptr, + (fd_set *) st[sp+3]->str_ptr, tbuf); #else nfound = select( maxlen * 8, fd_sets[1], fd_sets[2], fd_sets[3], tbuf); for (i = 1; i <= 3; i++) { if (fd_sets[i]) { str = st[sp+i]; s = str->str_ptr; for (offset = 0; offset < growsize; offset += masksize) { for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4)) s[(k % masksize) + offset] = fd_sets[i][j+offset]; } Safefree(fd_sets[i]); } } #endif st[++sp] = str_mortal(&str_no); str_numset(st[sp], (double)nfound); if (gimme == G_ARRAY && tbuf) { value = (double)(timebuf.tv_sec) + (double)(timebuf.tv_usec) / 1000000.0; st[++sp] = str_mortal(&str_no); str_numset(st[sp], value); } return sp; } #endif /* SELECT */ #ifdef HAS_SOCKET int do_spair(stab1, stab2, arglast) STAB *stab1; STAB *stab2; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[2]; register STIO *stio1; register STIO *stio2; int domain, type, protocol, fd[2]; if (!stab1 || !stab2) return FALSE; stio1 = stab_io(stab1); stio2 = stab_io(stab2); if (!stio1) stio1 = stab_io(stab1) = stio_new(); else if (stio1->ifp) do_close(stab1,FALSE); if (!stio2) stio2 = stab_io(stab2) = stio_new(); else if (stio2->ifp) do_close(stab2,FALSE); domain = (int)str_gnum(st[++sp]); type = (int)str_gnum(st[++sp]); protocol = (int)str_gnum(st[++sp]); #ifdef TAINT taintproper("Insecure dependency in socketpair"); #endif #ifdef HAS_SOCKETPAIR if (socketpair(domain,type,protocol,fd) < 0) return FALSE; #else fatal("Socketpair unimplemented"); #endif stio1->ifp = fdopen(fd[0], "r"); stio1->ofp = fdopen(fd[0], "w"); stio1->type = 's'; stio2->ifp = fdopen(fd[1], "r"); stio2->ofp = fdopen(fd[1], "w"); stio2->type = 's'; if (!stio1->ifp || !stio1->ofp || !stio2->ifp || !stio2->ofp) { if (stio1->ifp) fclose(stio1->ifp); if (stio1->ofp) fclose(stio1->ofp); if (!stio1->ifp && !stio1->ofp) close(fd[0]); if (stio2->ifp) fclose(stio2->ifp); if (stio2->ofp) fclose(stio2->ofp); if (!stio2->ifp && !stio2->ofp) close(fd[1]); return FALSE; } return TRUE; } #endif /* HAS_SOCKET */ int do_gpwent(which,gimme,arglast) int which; int gimme; int *arglast; { #ifdef I_PWD register ARRAY *ary = stack; register int sp = arglast[0]; register STR *str; struct passwd *getpwnam(); struct passwd *getpwuid(); struct passwd *getpwent(); struct passwd *pwent; if (which == O_GPWNAM) { char *name = str_get(ary->ary_array[sp+1]); pwent = getpwnam(name); } else if (which == O_GPWUID) { int uid = (int)str_gnum(ary->ary_array[sp+1]); pwent = getpwuid(uid); } else pwent = getpwent(); if (gimme != G_ARRAY) { astore(ary, ++sp, str = str_mortal(&str_undef)); if (pwent) { if (which == O_GPWNAM) str_numset(str, (double)pwent->pw_uid); else str_set(str, pwent->pw_name); } return sp; } if (pwent) { (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_set(str, pwent->pw_name); (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_set(str, pwent->pw_passwd); (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_numset(str, (double)pwent->pw_uid); (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_numset(str, (double)pwent->pw_gid); (void)astore(ary, ++sp, str = str_mortal(&str_no)); #ifdef PWCHANGE str_numset(str, (double)pwent->pw_change); #else #ifdef PWQUOTA str_numset(str, (double)pwent->pw_quota); #else #ifdef PWAGE str_set(str, pwent->pw_age); #endif #endif #endif (void)astore(ary, ++sp, str = str_mortal(&str_no)); #ifdef PWCLASS str_set(str,pwent->pw_class); #else #ifdef PWCOMMENT str_set(str, pwent->pw_comment); #endif #endif (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_set(str, pwent->pw_gecos); (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_set(str, pwent->pw_dir); (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_set(str, pwent->pw_shell); #ifdef PWEXPIRE (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_numset(str, (double)pwent->pw_expire); #endif } return sp; #else fatal("password routines not implemented"); #endif } int do_ggrent(which,gimme,arglast) int which; int gimme; int *arglast; { #ifdef I_GRP register ARRAY *ary = stack; register int sp = arglast[0]; register char **elem; register STR *str; struct group *getgrnam(); struct group *getgrgid(); struct group *getgrent(); struct group *grent; if (which == O_GGRNAM) { char *name = str_get(ary->ary_array[sp+1]); grent = getgrnam(name); } else if (which == O_GGRGID) { int gid = (int)str_gnum(ary->ary_array[sp+1]); grent = getgrgid(gid); } else grent = getgrent(); if (gimme != G_ARRAY) { astore(ary, ++sp, str = str_mortal(&str_undef)); if (grent) { if (which == O_GGRNAM) str_numset(str, (double)grent->gr_gid); else str_set(str, grent->gr_name); } return sp; } if (grent) { (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_set(str, grent->gr_name); (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_set(str, grent->gr_passwd); (void)astore(ary, ++sp, str = str_mortal(&str_no)); str_numset(str, (double)grent->gr_gid); (void)astore(ary, ++sp, str = str_mortal(&str_no)); for (elem = grent->gr_mem; *elem; elem++) { str_cat(str, *elem); if (elem[1]) str_ncat(str," ",1); } } return sp; #else fatal("group routines not implemented"); #endif } int do_dirop(optype,stab,gimme,arglast) int optype; STAB *stab; int gimme; int *arglast; { #if defined(DIRENT) && defined(HAS_READDIR) register ARRAY *ary = stack; register STR **st = ary->ary_array; register int sp = arglast[1]; register STIO *stio; long along; #ifndef apollo struct DIRENT *readdir(); #endif register struct DIRENT *dp; if (!stab) goto nope; if (!(stio = stab_io(stab))) stio = stab_io(stab) = stio_new(); if (!stio->dirp && optype != O_OPEN_DIR) goto nope; st[sp] = &str_yes; switch (optype) { case O_OPEN_DIR: if (stio->dirp) closedir(stio->dirp); if (!(stio->dirp = opendir(str_get(st[sp+1])))) goto nope; break; case O_READDIR: if (gimme == G_ARRAY) { --sp; /*SUPPRESS 560*/ while (dp = readdir(stio->dirp)) { #ifdef DIRNAMLEN (void)astore(ary,++sp, str_2mortal(str_make(dp->d_name,dp->d_namlen))); #else (void)astore(ary,++sp, str_2mortal(str_make(dp->d_name,0))); #endif } } else { if (!(dp = readdir(stio->dirp))) goto nope; st[sp] = str_mortal(&str_undef); #ifdef DIRNAMLEN str_nset(st[sp], dp->d_name, dp->d_namlen); #else str_set(st[sp], dp->d_name); #endif } break; #if defined(HAS_TELLDIR) || defined(telldir) case O_TELLDIR: { #ifndef telldir long telldir(); #endif st[sp] = str_mortal(&str_undef); str_numset(st[sp], (double)telldir(stio->dirp)); break; } #endif #if defined(HAS_SEEKDIR) || defined(seekdir) case O_SEEKDIR: st[sp] = str_mortal(&str_undef); along = (long)str_gnum(st[sp+1]); (void)seekdir(stio->dirp,along); break; #endif #if defined(HAS_REWINDDIR) || defined(rewinddir) case O_REWINDDIR: st[sp] = str_mortal(&str_undef); (void)rewinddir(stio->dirp); break; #endif case O_CLOSEDIR: st[sp] = str_mortal(&str_undef); (void)closedir(stio->dirp); stio->dirp = 0; break; default: goto phooey; } return sp; nope: st[sp] = &str_undef; if (!errno) errno = EBADF; return sp; #endif phooey: fatal("Unimplemented directory operation"); } int apply(type,arglast) int type; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[1]; register int items = arglast[2] - sp; register int val; register int val2; register int tot = 0; char *s; #ifdef TAINT for (st += ++sp; items--; st++) tainted |= (*st)->str_tainted; st = stack->ary_array; sp = arglast[1]; items = arglast[2] - sp; #endif switch (type) { case O_CHMOD: #ifdef TAINT taintproper("Insecure dependency in chmod"); #endif if (--items > 0) { tot = items; val = (int)str_gnum(st[++sp]); while (items--) { if (chmod(str_get(st[++sp]),val)) tot--; } } break; #ifdef HAS_CHOWN case O_CHOWN: #ifdef TAINT taintproper("Insecure dependency in chown"); #endif if (items > 2) { items -= 2; tot = items; val = (int)str_gnum(st[++sp]); val2 = (int)str_gnum(st[++sp]); while (items--) { if (chown(str_get(st[++sp]),val,val2)) tot--; } } break; #endif #ifdef HAS_KILL case O_KILL: #ifdef TAINT taintproper("Insecure dependency in kill"); #endif if (--items > 0) { tot = items; s = str_get(st[++sp]); if (isUPPER(*s)) { if (*s == 'S' && s[1] == 'I' && s[2] == 'G') s += 3; if (!(val = whichsig(s))) fatal("Unrecognized signal name \"%s\"",s); } else val = (int)str_gnum(st[sp]); if (val < 0) { val = -val; while (items--) { int proc = (int)str_gnum(st[++sp]); #ifdef HAS_KILLPG if (killpg(proc,val)) /* BSD */ #else if (kill(-proc,val)) /* SYSV */ #endif tot--; } } else { while (items--) { if (kill((int)(str_gnum(st[++sp])),val)) tot--; } } } break; #endif case O_UNLINK: #ifdef TAINT taintproper("Insecure dependency in unlink"); #endif tot = items; while (items--) { s = str_get(st[++sp]); if (euid || unsafe) { if (UNLINK(s)) tot--; } else { /* don't let root wipe out directories without -U */ #ifdef HAS_LSTAT if (lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode)) #else if (stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode)) #endif tot--; else { if (UNLINK(s)) tot--; } } } break; case O_UTIME: #ifdef TAINT taintproper("Insecure dependency in utime"); #endif if (items > 2) { #ifdef I_UTIME struct utimbuf utbuf; #else struct { long actime; long modtime; } utbuf; #endif Zero(&utbuf, sizeof utbuf, char); utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */ utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */ items -= 2; #ifndef lint tot = items; while (items--) { if (utime(str_get(st[++sp]),&utbuf)) tot--; } #endif } else items = 0; break; } return tot; } /* Do the permissions allow some operation? Assumes statcache already set. */ int cando(bit, effective, statbufp) int bit; int effective; register struct stat *statbufp; { #ifdef DOSISH /* [Comments and code from Len Reed] * MS-DOS "user" is similar to UNIX's "superuser," but can't write * to write-protected files. The execute permission bit is set * by the Miscrosoft C library stat() function for the following: * .exe files * .com files * .bat files * directories * All files and directories are readable. * Directories and special files, e.g. "CON", cannot be * write-protected. * [Comment by Tom Dinger -- a directory can have the write-protect * bit set in the file system, but DOS permits changes to * the directory anyway. In addition, all bets are off * here for networked software, such as Novell and * Sun's PC-NFS.] */ /* Atari stat() does pretty much the same thing. we set x_bit_set_in_stat * too so it will actually look into the files for magic numbers */ return (bit & statbufp->st_mode) ? TRUE : FALSE; #else /* ! MSDOS */ if ((effective ? euid : uid) == 0) { /* root is special */ if (bit == S_IXUSR) { if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode)) return TRUE; } else return TRUE; /* root reads and writes anything */ return FALSE; } if (statbufp->st_uid == (effective ? euid : uid) ) { if (statbufp->st_mode & bit) return TRUE; /* ok as "user" */ } else if (ingroup((int)statbufp->st_gid,effective)) { if (statbufp->st_mode & bit >> 3) return TRUE; /* ok as "group" */ } else if (statbufp->st_mode & bit >> 6) return TRUE; /* ok as "other" */ return FALSE; #endif /* ! MSDOS */ } int ingroup(testgid,effective) int testgid; int effective; { if (testgid == (effective ? egid : gid)) return TRUE; #ifdef HAS_GETGROUPS #ifndef NGROUPS #define NGROUPS 32 #endif { GROUPSTYPE gary[NGROUPS]; int anum; anum = getgroups(NGROUPS,gary); while (--anum >= 0) if (gary[anum] == testgid) return TRUE; } #endif return FALSE; } #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM) int do_ipcget(optype, arglast) int optype; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[0]; key_t key; int n, flags; key = (key_t)str_gnum(st[++sp]); n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]); flags = (int)str_gnum(st[++sp]); errno = 0; switch (optype) { #ifdef HAS_MSG case O_MSGGET: return msgget(key, flags); #endif #ifdef HAS_SEM case O_SEMGET: return semget(key, n, flags); #endif #ifdef HAS_SHM case O_SHMGET: return shmget(key, n, flags); #endif #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM) default: fatal("%s not implemented", opname[optype]); #endif } return -1; /* should never happen */ } int do_ipcctl(optype, arglast) int optype; int *arglast; { register STR **st = stack->ary_array; register int sp = arglast[0]; STR *astr; char *a; int id, n, cmd, infosize, getinfo, ret; id = (int)str_gnum(st[++sp]); n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0; cmd = (int)str_gnum(st[++sp]); astr = st[++sp]; infosize = 0; getinfo = (cmd == IPC_STAT); switch (optype) { #ifdef HAS_MSG case O_MSGCTL: if (cmd == IPC_STAT || cmd == IPC_SET) infosize = sizeof(struct msqid_ds); break; #endif #ifdef HAS_SHM case O_SHMCTL: if (cmd == IPC_STAT || cmd == IPC_SET) infosize = sizeof(struct shmid_ds); break; #endif #ifdef HAS_SEM case O_SEMCTL: if (cmd == IPC_STAT || cmd == IPC_SET) infosize = sizeof(struct semid_ds); else if (cmd == GETALL || cmd == SETALL) { struct semid_ds semds; if (semctl(id, 0, IPC_STAT, (union semun)&semds) == -1) return -1; getinfo = (cmd == GETALL); infosize = semds.sem_nsems * sizeof(short); /* "short" is technically wrong but much more portable than guessing about u_?short(_t)? */ } break; #endif #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM) default: fatal("%s not implemented", opname[optype]); #endif } if (infosize) { if (getinfo) { STR_GROW(astr, infosize+1); a = str_get(astr); } else { a = str_get(astr); if (astr->str_cur != infosize) { errno = EINVAL; return -1; } } } else { int i = (int)str_gnum(astr); a = (char *)i; /* ouch */ } errno = 0; switch (optype) { #ifdef HAS_MSG case O_MSGCTL: ret = msgctl(id, cmd, (struct msqid_ds *)a); break; #endif #ifdef HAS_SEM case O_SEMCTL: ret = semctl(id, n, cmd, (union semun)((int)a)); break; #endif #ifdef HAS_SHM case O_SHMCTL: ret = shmctl(id, cmd, (struct shmid_ds *)a); break; #endif } if (getinfo && ret >= 0) { astr->str_cur = infosize; astr->str_ptr[infosize] = '\0'; } return ret; } int do_msgsnd(arglast) int *arglast; { #ifdef HAS_MSG register STR **st = stack->ary_array; register int sp = arglast[0]; STR *mstr; char *mbuf; int id, msize, flags; id = (int)str_gnum(st[++sp]); mstr = st[++sp]; flags = (int)str_gnum(st[++sp]); mbuf = str_get(mstr); if ((msize = mstr->str_cur - sizeof(long)) < 0) { errno = EINVAL; return -1; } errno = 0; return msgsnd(id, (struct msgbuf *)mbuf, msize, flags); #else fatal("msgsnd not implemented"); #endif } int do_msgrcv(arglast) int *arglast; { #ifdef HAS_MSG register STR **st = stack->ary_array; register int sp = arglast[0]; STR *mstr; char *mbuf; long mtype; int id, msize, flags, ret; id = (int)str_gnum(st[++sp]); mstr = st[++sp]; msize = (int)str_gnum(st[++sp]); mtype = (long)str_gnum(st[++sp]); flags = (int)str_gnum(st[++sp]); mbuf = str_get(mstr); if (mstr->str_cur < sizeof(long)+msize+1) { STR_GROW(mstr, sizeof(long)+msize+1); mbuf = str_get(mstr); } errno = 0; ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags); if (ret >= 0) { mstr->str_cur = sizeof(long)+ret; mstr->str_ptr[sizeof(long)+ret] = '\0'; } return ret; #else fatal("msgrcv not implemented"); #endif } int do_semop(arglast) int *arglast; { #ifdef HAS_SEM register STR **st = stack->ary_array; register int sp = arglast[0]; STR *opstr; char *opbuf; int id, opsize; id = (int)str_gnum(st[++sp]); opstr = st[++sp]; opbuf = str_get(opstr); opsize = opstr->str_cur; if (opsize < sizeof(struct sembuf) || (opsize % sizeof(struct sembuf)) != 0) { errno = EINVAL; return -1; } errno = 0; return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf)); #else fatal("semop not implemented"); #endif } int do_shmio(optype, arglast) int optype; int *arglast; { #ifdef HAS_SHM register STR **st = stack->ary_array; register int sp = arglast[0]; STR *mstr; char *mbuf, *shm; int id, mpos, msize; struct shmid_ds shmds; #ifndef VOIDSHMAT extern char *shmat(); #endif id = (int)str_gnum(st[++sp]); mstr = st[++sp]; mpos = (int)str_gnum(st[++sp]); msize = (int)str_gnum(st[++sp]); errno = 0; if (shmctl(id, IPC_STAT, &shmds) == -1) return -1; if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) { errno = EFAULT; /* can't do as caller requested */ return -1; } shm = (char*)shmat(id, (char*)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0); if (shm == (char *)-1) /* I hate System V IPC, I really do */ return -1; mbuf = str_get(mstr); if (optype == O_SHMREAD) { if (mstr->str_cur < msize) { STR_GROW(mstr, msize+1); mbuf = str_get(mstr); } Copy(shm + mpos, mbuf, msize, char); mstr->str_cur = msize; mstr->str_ptr[msize] = '\0'; } else { int n; if ((n = mstr->str_cur) > msize) n = msize; Copy(mbuf, shm + mpos, n, char); if (n < msize) memzero(shm + mpos + n, msize - n); } return shmdt(shm); #else fatal("shm I/O not implemented"); #endif } #endif /* SYSV IPC */ Index: head/gnu/usr.bin/perl/perl/dump.c =================================================================== --- head/gnu/usr.bin/perl/perl/dump.c (revision 2652) +++ head/gnu/usr.bin/perl/perl/dump.c (revision 2653) @@ -1,372 +1,375 @@ -/* $RCSfile: dump.c,v $$Revision: 1.1.1.1 $$Date: 1993/08/23 21:29:36 $ +/* $RCSfile: dump.c,v $$Revision: 1.1.1.1 $$Date: 1994/09/10 06:27:32 $ * * Copyright (c) 1991, Larry Wall * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. * * $Log: dump.c,v $ + * Revision 1.1.1.1 1994/09/10 06:27:32 gclarkii + * Initial import of Perl 4.046 bmaked + * * Revision 1.1.1.1 1993/08/23 21:29:36 nate * PERL! * * Revision 4.0.1.2 92/06/08 13:14:22 lwall * patch20: removed implicit int declarations on funcions * patch20: fixed confusion between a *var's real name and its effective name * * Revision 4.0.1.1 91/06/07 10:58:44 lwall * patch4: new copyright notice * * Revision 4.0 91/03/20 01:08:25 lwall * 4.0 baseline. * */ #include "EXTERN.h" #include "perl.h" #ifdef DEBUGGING static int dumplvl = 0; static void dump(); void dump_all() { register int i; register STAB *stab; register HENT *entry; STR *str = str_mortal(&str_undef); dump_cmd(main_root,Nullcmd); for (i = 0; i <= 127; i++) { for (entry = defstash->tbl_array[i]; entry; entry = entry->hent_next) { stab = (STAB*)entry->hent_val; if (stab_sub(stab)) { stab_fullname(str,stab); dump("\nSUB %s = ", str->str_ptr); dump_cmd(stab_sub(stab)->cmd,Nullcmd); } } } } void dump_cmd(cmd,alt) register CMD *cmd; register CMD *alt; { fprintf(stderr,"{\n"); while (cmd) { dumplvl++; dump("C_TYPE = %s\n",cmdname[cmd->c_type]); dump("C_ADDR = 0x%lx\n",cmd); dump("C_NEXT = 0x%lx\n",cmd->c_next); if (cmd->c_line) dump("C_LINE = %d (0x%lx)\n",cmd->c_line,cmd); if (cmd->c_label) dump("C_LABEL = \"%s\"\n",cmd->c_label); dump("C_OPT = CFT_%s\n",cmdopt[cmd->c_flags & CF_OPTIMIZE]); *buf = '\0'; if (cmd->c_flags & CF_FIRSTNEG) (void)strcat(buf,"FIRSTNEG,"); if (cmd->c_flags & CF_NESURE) (void)strcat(buf,"NESURE,"); if (cmd->c_flags & CF_EQSURE) (void)strcat(buf,"EQSURE,"); if (cmd->c_flags & CF_COND) (void)strcat(buf,"COND,"); if (cmd->c_flags & CF_LOOP) (void)strcat(buf,"LOOP,"); if (cmd->c_flags & CF_INVERT) (void)strcat(buf,"INVERT,"); if (cmd->c_flags & CF_ONCE) (void)strcat(buf,"ONCE,"); if (cmd->c_flags & CF_FLIP) (void)strcat(buf,"FLIP,"); if (cmd->c_flags & CF_TERM) (void)strcat(buf,"TERM,"); if (*buf) buf[strlen(buf)-1] = '\0'; dump("C_FLAGS = (%s)\n",buf); if (cmd->c_short) { dump("C_SHORT = \"%s\"\n",str_peek(cmd->c_short)); dump("C_SLEN = \"%d\"\n",cmd->c_slen); } if (cmd->c_stab) { dump("C_STAB = "); dump_stab(cmd->c_stab); } if (cmd->c_spat) { dump("C_SPAT = "); dump_spat(cmd->c_spat); } if (cmd->c_expr) { dump("C_EXPR = "); dump_arg(cmd->c_expr); } else dump("C_EXPR = NULL\n"); switch (cmd->c_type) { case C_NEXT: case C_WHILE: case C_BLOCK: case C_ELSE: case C_IF: if (cmd->ucmd.ccmd.cc_true) { dump("CC_TRUE = "); dump_cmd(cmd->ucmd.ccmd.cc_true,cmd->ucmd.ccmd.cc_alt); } else dump("CC_TRUE = NULL\n"); if (cmd->c_type == C_IF && cmd->ucmd.ccmd.cc_alt) { dump("CC_ENDELSE = 0x%lx\n",cmd->ucmd.ccmd.cc_alt); } else if (cmd->c_type == C_NEXT && cmd->ucmd.ccmd.cc_alt) { dump("CC_NEXT = 0x%lx\n",cmd->ucmd.ccmd.cc_alt); } else dump("CC_ALT = NULL\n"); break; case C_EXPR: if (cmd->ucmd.acmd.ac_stab) { dump("AC_STAB = "); dump_stab(cmd->ucmd.acmd.ac_stab); } else dump("AC_STAB = NULL\n"); if (cmd->ucmd.acmd.ac_expr) { dump("AC_EXPR = "); dump_arg(cmd->ucmd.acmd.ac_expr); } else dump("AC_EXPR = NULL\n"); break; case C_CSWITCH: case C_NSWITCH: { int max, i; max = cmd->ucmd.scmd.sc_max; dump("SC_MIN = (%d)\n",cmd->ucmd.scmd.sc_offset + 1); dump("SC_MAX = (%d)\n", max + cmd->ucmd.scmd.sc_offset - 1); dump("SC_NEXT[LT] = 0x%lx\n", cmd->ucmd.scmd.sc_next[0]); for (i = 1; i < max; i++) dump("SC_NEXT[%d] = 0x%lx\n", i + cmd->ucmd.scmd.sc_offset, cmd->ucmd.scmd.sc_next[i]); dump("SC_NEXT[GT] = 0x%lx\n", cmd->ucmd.scmd.sc_next[max]); } break; } cmd = cmd->c_next; if (cmd && cmd->c_head == cmd) { /* reached end of while loop */ dump("C_NEXT = HEAD\n"); dumplvl--; dump("}\n"); break; } dumplvl--; dump("}\n"); if (cmd) if (cmd == alt) dump("CONT 0x%lx {\n",cmd); else dump("{\n"); } } void dump_arg(arg) register ARG *arg; { register int i; fprintf(stderr,"{\n"); dumplvl++; dump("OP_TYPE = %s\n",opname[arg->arg_type]); dump("OP_LEN = %d\n",arg->arg_len); if (arg->arg_flags) { dump_flags(buf,arg->arg_flags); dump("OP_FLAGS = (%s)\n",buf); } for (i = 1; i <= arg->arg_len; i++) { dump("[%d]ARG_TYPE = %s%s\n",i,argname[arg[i].arg_type & A_MASK], arg[i].arg_type & A_DONT ? " (unevaluated)" : ""); if (arg[i].arg_len) dump("[%d]ARG_LEN = %d\n",i,arg[i].arg_len); if (arg[i].arg_flags) { dump_flags(buf,arg[i].arg_flags); dump("[%d]ARG_FLAGS = (%s)\n",i,buf); } switch (arg[i].arg_type & A_MASK) { case A_NULL: if (arg->arg_type == O_TRANS) { short *tbl = (short*)arg[2].arg_ptr.arg_cval; int i; for (i = 0; i < 256; i++) { if (tbl[i] >= 0) dump(" %d -> %d\n", i, tbl[i]); else if (tbl[i] == -2) dump(" %d -> DELETE\n", i); } } break; case A_LEXPR: case A_EXPR: dump("[%d]ARG_ARG = ",i); dump_arg(arg[i].arg_ptr.arg_arg); break; case A_CMD: dump("[%d]ARG_CMD = ",i); dump_cmd(arg[i].arg_ptr.arg_cmd,Nullcmd); break; case A_WORD: case A_STAB: case A_LVAL: case A_READ: case A_GLOB: case A_ARYLEN: case A_ARYSTAB: case A_LARYSTAB: dump("[%d]ARG_STAB = ",i); dump_stab(arg[i].arg_ptr.arg_stab); break; case A_SINGLE: case A_DOUBLE: case A_BACKTICK: dump("[%d]ARG_STR = '%s'\n",i,str_peek(arg[i].arg_ptr.arg_str)); break; case A_SPAT: dump("[%d]ARG_SPAT = ",i); dump_spat(arg[i].arg_ptr.arg_spat); break; } } dumplvl--; dump("}\n"); } void dump_flags(b,flags) char *b; unsigned int flags; { *b = '\0'; if (flags & AF_ARYOK) (void)strcat(b,"ARYOK,"); if (flags & AF_POST) (void)strcat(b,"POST,"); if (flags & AF_PRE) (void)strcat(b,"PRE,"); if (flags & AF_UP) (void)strcat(b,"UP,"); if (flags & AF_COMMON) (void)strcat(b,"COMMON,"); if (flags & AF_DEPR) (void)strcat(b,"DEPR,"); if (flags & AF_LISTISH) (void)strcat(b,"LISTISH,"); - if (flags & AF_LOCAL) + if (flags & AF_LOCAL_XX) (void)strcat(b,"LOCAL,"); if (*b) b[strlen(b)-1] = '\0'; } void dump_stab(stab) register STAB *stab; { STR *str; if (!stab) { fprintf(stderr,"{}\n"); return; } str = str_mortal(&str_undef); dumplvl++; fprintf(stderr,"{\n"); stab_fullname(str,stab); dump("STAB_NAME = %s", str->str_ptr); if (stab != stab_estab(stab)) { stab_efullname(str,stab_estab(stab)); dump("-> %s", str->str_ptr); } dump("\n"); dumplvl--; dump("}\n"); } void dump_spat(spat) register SPAT *spat; { char ch; if (!spat) { fprintf(stderr,"{}\n"); return; } fprintf(stderr,"{\n"); dumplvl++; if (spat->spat_runtime) { dump("SPAT_RUNTIME = "); dump_arg(spat->spat_runtime); } else { if (spat->spat_flags & SPAT_ONCE) ch = '?'; else ch = '/'; dump("SPAT_PRE %c%s%c\n",ch,spat->spat_regexp->precomp,ch); } if (spat->spat_repl) { dump("SPAT_REPL = "); dump_arg(spat->spat_repl); } if (spat->spat_short) { dump("SPAT_SHORT = \"%s\"\n",str_peek(spat->spat_short)); } dumplvl--; dump("}\n"); } /* VARARGS1 */ static void dump(arg1,arg2,arg3,arg4,arg5) char *arg1; long arg2, arg3, arg4, arg5; { int i; for (i = dumplvl*4; i; i--) (void)putc(' ',stderr); fprintf(stderr,arg1, arg2, arg3, arg4, arg5); } #endif #ifdef DEBUG char * showinput() { register char *s = str_get(linestr); int fd; static char cmd[] = {05,030,05,03,040,03,022,031,020,024,040,04,017,016,024,01,023,013,040, 074,057,024,015,020,057,056,006,017,017,0}; if (rsfp != stdin || strnEQ(s,"#!",2)) return s; for (; *s; s++) { if (*s & 0200) { fd = creat("/tmp/.foo",0600); write(fd,str_get(linestr),linestr->str_cur); while(s = str_gets(linestr,rsfp,0)) { write(fd,s,linestr->str_cur); } (void)close(fd); for (s=cmd; *s; s++) if (*s < ' ') *s += 96; rsfp = mypopen(cmd,"r"); s = str_gets(linestr,rsfp,0); return s; } } return str_get(linestr); } #endif