1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1994, by Sun Microsytems, Inc. 24*7c478bd9Sstevel@tonic-gate */ 25*7c478bd9Sstevel@tonic-gate 26*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate /* 29*7c478bd9Sstevel@tonic-gate * Includes 30*7c478bd9Sstevel@tonic-gate */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #include <unistd.h> 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 35*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 36*7c478bd9Sstevel@tonic-gate #include <string.h> 37*7c478bd9Sstevel@tonic-gate #include <libintl.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate #include "new.h" 43*7c478bd9Sstevel@tonic-gate #include "queue.h" 44*7c478bd9Sstevel@tonic-gate #include "source.h" 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate /* 48*7c478bd9Sstevel@tonic-gate * Typedefs 49*7c478bd9Sstevel@tonic-gate */ 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate typedef struct source { 52*7c478bd9Sstevel@tonic-gate queue_node_t qn; 53*7c478bd9Sstevel@tonic-gate char *path; 54*7c478bd9Sstevel@tonic-gate FILE *instream; 55*7c478bd9Sstevel@tonic-gate int linenum; 56*7c478bd9Sstevel@tonic-gate boolean_t isatty; 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate } source_t; 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate /* 62*7c478bd9Sstevel@tonic-gate * Defines 63*7c478bd9Sstevel@tonic-gate */ 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate #define HOME "HOME" 66*7c478bd9Sstevel@tonic-gate #define PREXRC ".prexrc" 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate /* 70*7c478bd9Sstevel@tonic-gate * Globals 71*7c478bd9Sstevel@tonic-gate */ 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate static queue_node_t stack; 74*7c478bd9Sstevel@tonic-gate static source_t *top; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate /* 78*7c478bd9Sstevel@tonic-gate * source_init() - initializes the source stack 79*7c478bd9Sstevel@tonic-gate */ 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate void 82*7c478bd9Sstevel@tonic-gate source_init(void) 83*7c478bd9Sstevel@tonic-gate { 84*7c478bd9Sstevel@tonic-gate source_t *new_p; 85*7c478bd9Sstevel@tonic-gate struct stat statbuf; 86*7c478bd9Sstevel@tonic-gate char *home; 87*7c478bd9Sstevel@tonic-gate int retval; 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate /* initialize the stack queue head */ 91*7c478bd9Sstevel@tonic-gate queue_init(&stack); 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate /* stick the standard input on the bottom of the stack */ 94*7c478bd9Sstevel@tonic-gate new_p = new(source_t); 95*7c478bd9Sstevel@tonic-gate queue_init(&new_p->qn); 96*7c478bd9Sstevel@tonic-gate new_p->path = strdup("<STDIN>"); 97*7c478bd9Sstevel@tonic-gate new_p->instream = stdin; 98*7c478bd9Sstevel@tonic-gate new_p->linenum = 1; 99*7c478bd9Sstevel@tonic-gate new_p->isatty = isatty(fileno(new_p->instream)); 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate (void) queue_prepend(&stack, &new_p->qn); 102*7c478bd9Sstevel@tonic-gate top = new_p; 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate /* 105*7c478bd9Sstevel@tonic-gate * since we are pushing onto a stack, we invert the search order * 106*7c478bd9Sstevel@tonic-gate * and push the prexrc in the current directory on next. 107*7c478bd9Sstevel@tonic-gate */ 108*7c478bd9Sstevel@tonic-gate retval = stat(PREXRC, &statbuf); 109*7c478bd9Sstevel@tonic-gate if (retval != -1) { 110*7c478bd9Sstevel@tonic-gate source_file(PREXRC); 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate home = getenv(HOME); 113*7c478bd9Sstevel@tonic-gate if (home) { 114*7c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate if ((strlen(home) + strlen(PREXRC) + 2) < (size_t) MAXPATHLEN) { 117*7c478bd9Sstevel@tonic-gate (void) sprintf(path, "%s/%s", home, PREXRC); 118*7c478bd9Sstevel@tonic-gate retval = stat(path, &statbuf); 119*7c478bd9Sstevel@tonic-gate if (retval != -1) { 120*7c478bd9Sstevel@tonic-gate source_file(path); 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate } 123*7c478bd9Sstevel@tonic-gate } 124*7c478bd9Sstevel@tonic-gate } /* end source_init */ 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* 128*7c478bd9Sstevel@tonic-gate * source_file() - pushes a new source onto the stack 129*7c478bd9Sstevel@tonic-gate */ 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate void 132*7c478bd9Sstevel@tonic-gate source_file(char *path) 133*7c478bd9Sstevel@tonic-gate { 134*7c478bd9Sstevel@tonic-gate FILE *newfile; 135*7c478bd9Sstevel@tonic-gate source_t *new_p; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate newfile = fopen(path, "r"); 138*7c478bd9Sstevel@tonic-gate if (!newfile) { 139*7c478bd9Sstevel@tonic-gate semantic_err(gettext("cannot open \"%s\""), path); 140*7c478bd9Sstevel@tonic-gate return; 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate new_p = new(source_t); 143*7c478bd9Sstevel@tonic-gate queue_init(&new_p->qn); 144*7c478bd9Sstevel@tonic-gate new_p->path = strdup(path); 145*7c478bd9Sstevel@tonic-gate new_p->instream = newfile; 146*7c478bd9Sstevel@tonic-gate new_p->linenum = 1; 147*7c478bd9Sstevel@tonic-gate new_p->isatty = isatty(fileno(new_p->instream)); 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate (void) queue_prepend(&stack, &new_p->qn); 150*7c478bd9Sstevel@tonic-gate top = new_p; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate } /* end source_file */ 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate /* 156*7c478bd9Sstevel@tonic-gate * source_input() - lexical analyzer input routine 157*7c478bd9Sstevel@tonic-gate */ 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate extern void quit(boolean_t, boolean_t); 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate int 162*7c478bd9Sstevel@tonic-gate source_input(void) 163*7c478bd9Sstevel@tonic-gate { 164*7c478bd9Sstevel@tonic-gate int c; 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate if (!top) 167*7c478bd9Sstevel@tonic-gate return (0); 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate c = getc(top->instream); 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate if (c == EOF) { 172*7c478bd9Sstevel@tonic-gate /* 173*7c478bd9Sstevel@tonic-gate * If we get an EOF at the top level, we quit if we are * 174*7c478bd9Sstevel@tonic-gate * non-interactive, pretend we saw a new-line if we are * 175*7c478bd9Sstevel@tonic-gate * interactive. 176*7c478bd9Sstevel@tonic-gate */ 177*7c478bd9Sstevel@tonic-gate if (top->instream == stdin) { 178*7c478bd9Sstevel@tonic-gate if (top->isatty) { 179*7c478bd9Sstevel@tonic-gate source_output('\n'); 180*7c478bd9Sstevel@tonic-gate return ('\n'); 181*7c478bd9Sstevel@tonic-gate } else 182*7c478bd9Sstevel@tonic-gate quit(B_TRUE, B_TRUE); 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate /* we've exhausted the current stream, pop it, delete it ... */ 185*7c478bd9Sstevel@tonic-gate if (top->path) 186*7c478bd9Sstevel@tonic-gate free(top->path); 187*7c478bd9Sstevel@tonic-gate (void) fclose(top->instream); 188*7c478bd9Sstevel@tonic-gate (void) queue_remove(&top->qn); 189*7c478bd9Sstevel@tonic-gate free(top); 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate /* point to the new top level i/o stream */ 192*7c478bd9Sstevel@tonic-gate top = (source_t *) queue_next(&stack, &stack); 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate if (!top) 195*7c478bd9Sstevel@tonic-gate return (0); 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate /* trigger a prompt if neccessary */ 198*7c478bd9Sstevel@tonic-gate prompt(); 199*7c478bd9Sstevel@tonic-gate return (source_input()); 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate return (c); 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate } /* end source_input */ 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate /* 207*7c478bd9Sstevel@tonic-gate * source_unput() - lexical analyzer unput routine 208*7c478bd9Sstevel@tonic-gate */ 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate void 211*7c478bd9Sstevel@tonic-gate source_unput(int c) 212*7c478bd9Sstevel@tonic-gate { 213*7c478bd9Sstevel@tonic-gate if (top) 214*7c478bd9Sstevel@tonic-gate (void) ungetc(c, top->instream); 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate } /* end source_unput */ 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate /* 220*7c478bd9Sstevel@tonic-gate * source_output() - lexical analyzer output routine 221*7c478bd9Sstevel@tonic-gate */ 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate void 224*7c478bd9Sstevel@tonic-gate source_output(int c) 225*7c478bd9Sstevel@tonic-gate { 226*7c478bd9Sstevel@tonic-gate (void) putc(c, stdout); 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate } /* end source_output */ 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate /* 232*7c478bd9Sstevel@tonic-gate * source_nl() - increment the line counter 233*7c478bd9Sstevel@tonic-gate */ 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate void 236*7c478bd9Sstevel@tonic-gate source_nl(void) 237*7c478bd9Sstevel@tonic-gate { 238*7c478bd9Sstevel@tonic-gate if (top) 239*7c478bd9Sstevel@tonic-gate top->linenum++; 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate } /* end source_nl */ 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate /* 245*7c478bd9Sstevel@tonic-gate * yyerror() - 246*7c478bd9Sstevel@tonic-gate */ 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate extern char yytext[]; 249*7c478bd9Sstevel@tonic-gate extern int g_linenum; 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate void 252*7c478bd9Sstevel@tonic-gate yyerror(char *s) 253*7c478bd9Sstevel@tonic-gate { 254*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 255*7c478bd9Sstevel@tonic-gate gettext("\"%s\", line %d: %s on or before \"%s\"\n"), 256*7c478bd9Sstevel@tonic-gate top->path, top->linenum, s, yytext); 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate /* 262*7c478bd9Sstevel@tonic-gate * yywrap() - 263*7c478bd9Sstevel@tonic-gate */ 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate int 266*7c478bd9Sstevel@tonic-gate yywrap() 267*7c478bd9Sstevel@tonic-gate { 268*7c478bd9Sstevel@tonic-gate return (1); 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate } /* end yywrap */ 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate /* 274*7c478bd9Sstevel@tonic-gate * prompt() - 275*7c478bd9Sstevel@tonic-gate */ 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate extern char **g_argv; 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate void 280*7c478bd9Sstevel@tonic-gate prompt(void) 281*7c478bd9Sstevel@tonic-gate { 282*7c478bd9Sstevel@tonic-gate if (top && top->isatty) 283*7c478bd9Sstevel@tonic-gate (void) printf("%s> ", g_argv[0]); 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate } /* end g_prompt */ 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate /* 289*7c478bd9Sstevel@tonic-gate * semantic_err() - reports a semantic error 290*7c478bd9Sstevel@tonic-gate */ 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate void 293*7c478bd9Sstevel@tonic-gate semantic_err(char *format, ...) 294*7c478bd9Sstevel@tonic-gate { 295*7c478bd9Sstevel@tonic-gate va_list ap; 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate va_start(ap, format); 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate if (!top) 300*7c478bd9Sstevel@tonic-gate return; 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("\"%s\", line %d: semantic error: "), 303*7c478bd9Sstevel@tonic-gate top->path, top->linenum); 304*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, format, ap); 305*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("\n")); 306*7c478bd9Sstevel@tonic-gate 307*7c478bd9Sstevel@tonic-gate } /* end semantic_err */ 308