1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/* Copyright (c) 1988 AT&T */
27/* All Rights Reserved */
28
29/* Copyright 1976, Bell Telephone Laboratories, Inc. */
30
31#pragma ident	"%Z%%M%	%I%	%E% SMI"
32
33#include <string.h>
34#include "once.h"
35#include "sgs.h"
36#include <locale.h>
37#include <limits.h>
38
39static wchar_t  L_INITIAL[] = {'I', 'N', 'I', 'T', 'I', 'A', 'L', 0};
40static void get1core(void);
41static void free1core(void);
42static void get2core(void);
43static void free2core(void);
44static void get3core(void);
45#ifdef DEBUG
46static void free3core(void);
47#endif
48
49int
50main(int argc, char **argv)
51{
52	int i;
53	int c;
54	char *path = NULL;
55	Boolean eoption = 0, woption = 0;
56
57	sargv = argv;
58	sargc = argc;
59	(void) setlocale(LC_ALL, "");
60#ifdef DEBUG
61	while ((c = getopt(argc, argv, "dyctvnewVQ:Y:")) != EOF) {
62#else
63	while ((c = getopt(argc, argv, "ctvnewVQ:Y:")) != EOF) {
64#endif
65		switch (c) {
66#ifdef DEBUG
67			case 'd':
68				debug++;
69				break;
70			case 'y':
71				yydebug = TRUE;
72				break;
73#endif
74			case 'V':
75				(void) fprintf(stderr, "lex: %s %s\n",
76				    (const char *)SGU_PKG,
77				    (const char *)SGU_REL);
78				break;
79			case 'Q':
80				v_stmp = optarg;
81				if (*v_stmp != 'y' && *v_stmp != 'n')
82					error(
83					"lex: -Q should be followed by [y/n]");
84				break;
85			case 'Y':
86				path = (char *)malloc(strlen(optarg) +
87				    sizeof ("/nceucform") + 1);
88				path = strcpy(path, optarg);
89				break;
90			case 'c':
91				ratfor = FALSE;
92				break;
93			case 't':
94				fout = stdout;
95				break;
96			case 'v':
97				report = 1;
98				break;
99			case 'n':
100				report = 0;
101				break;
102			case 'w':
103			case 'W':
104				woption = 1;
105				handleeuc = 1;
106				widecio = 1;
107				break;
108			case 'e':
109			case 'E':
110				eoption = 1;
111				handleeuc = 1;
112				widecio = 0;
113				break;
114			default:
115				(void) fprintf(stderr,
116				"Usage: lex [-ewctvnVY] [-Q(y/n)] [file]\n");
117				exit(1);
118		}
119	}
120	if (woption && eoption) {
121		error(
122		"You may not specify both -w and -e simultaneously.");
123	}
124	no_input = argc - optind;
125	if (no_input) {
126		/* XCU4: recognize "-" file operand for stdin */
127		if (strcmp(argv[optind], "-") == 0)
128			fin = stdin;
129		else {
130			fin = fopen(argv[optind], "r");
131			if (fin == NULL)
132				error(
133				"Can't open input file -- %s", argv[optind]);
134		}
135	} else
136		fin = stdin;
137
138	/* may be gotten: def, subs, sname, schar, ccl, dchar */
139	(void) gch();
140
141	/* may be gotten: name, left, right, nullstr, parent */
142	get1core();
143
144	scopy(L_INITIAL, sp);
145	sname[0] = sp;
146	sp += slength(L_INITIAL) + 1;
147	sname[1] = 0;
148
149	/* XCU4: %x exclusive start */
150	exclusive[0] = 0;
151
152	if (!handleeuc) {
153		/*
154		 * Set ZCH and ncg to their default values
155		 * as they may be needed to handle %t directive.
156		 */
157		ZCH = ncg = NCH; /* ncg behaves as constant in this mode. */
158	}
159
160	/* may be disposed of: def, subs, dchar */
161	if (yyparse())
162		exit(1);	/* error return code */
163
164	if (handleeuc) {
165		ncg = ncgidtbl * 2;
166		ZCH = ncg;
167		if (ncg >= MAXNCG)
168			error(
169			"Too complex rules -- requires too many char groups.");
170		sortcgidtbl();
171	}
172	repbycgid(); /* Call this even in ASCII compat. mode. */
173
174	/*
175	 * maybe get:
176	 *		tmpstat, foll, positions, gotof, nexts,
177	 *		nchar, state, atable, sfall, cpackflg
178	 */
179	free1core();
180	get2core();
181	ptail();
182	mkmatch();
183#ifdef DEBUG
184	if (debug)
185		pccl();
186#endif
187	sect  = ENDSECTION;
188	if (tptr > 0)
189		cfoll(tptr-1);
190#ifdef DEBUG
191	if (debug)
192		pfoll();
193#endif
194	cgoto();
195#ifdef DEBUG
196	if (debug) {
197		(void) printf("Print %d states:\n", stnum + 1);
198		for (i = 0; i <= stnum; i++)
199			stprt(i);
200	}
201#endif
202	/*
203	 * may be disposed of:
204	 *		positions, tmpstat, foll, state, name,
205	 *		left, right, parent, ccl, schar, sname
206	 * maybe get:	 verify, advance, stoff
207	 */
208	free2core();
209	get3core();
210	layout();
211	/*
212	 * may be disposed of:
213	 *		verify, advance, stoff, nexts, nchar,
214	 *		gotof, atable, ccpackflg, sfall
215	 */
216
217#ifdef DEBUG
218	free3core();
219#endif
220
221	if (handleeuc) {
222		if (ratfor)
223			error("Ratfor is not supported by -w or -e option.");
224		path = EUCNAME;
225	}
226	else
227		path = ratfor ? RATNAME : CNAME;
228
229	fother = fopen(path, "r");
230	if (fother == NULL)
231		error("Lex driver missing, file %s", path);
232	while ((i = getc(fother)) != EOF)
233		(void) putc((char)i, fout);
234	(void) fclose(fother);
235	(void) fclose(fout);
236	if (report == 1)
237		statistics();
238	(void) fclose(stdout);
239	(void) fclose(stderr);
240	return (0);	/* success return code */
241}
242
243static void
244get1core(void)
245{
246	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
247	ccptr =	ccl = (CHR *)myalloc(CCLSIZE, sizeof (*ccl));
248	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
249	pcptr = pchar = (CHR *)myalloc(pchlen, sizeof (*pchar));
250	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
251	def = (CHR **)myalloc(DEFSIZE, sizeof (*def));
252	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
253	subs = (CHR **)myalloc(DEFSIZE, sizeof (*subs));
254	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
255	dp = dchar = (CHR *)myalloc(DEFCHAR, sizeof (*dchar));
256	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
257	sname = (CHR **)myalloc(STARTSIZE, sizeof (*sname));
258	/* XCU4: exclusive start array */
259	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
260	exclusive = (int *)myalloc(STARTSIZE, sizeof (*exclusive));
261	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
262	sp = schar = (CHR *)myalloc(STARTCHAR, sizeof (*schar));
263	if (ccl == 0 || def == 0 ||
264	    pchar == 0 || subs == 0 || dchar == 0 ||
265	    sname == 0 || exclusive == 0 || schar == 0)
266		error("Too little core to begin");
267}
268
269static void
270free1core(void)
271{
272	free(def);
273	free(subs);
274	free(dchar);
275}
276
277static void
278get2core(void)
279{
280	int i;
281	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
282	gotof = (int *)myalloc(nstates, sizeof (*gotof));
283	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
284	nexts = (int *)myalloc(ntrans, sizeof (*nexts));
285	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
286	nchar = (CHR *)myalloc(ntrans, sizeof (*nchar));
287	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
288	state = (int **)myalloc(nstates, sizeof (*state));
289	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
290	atable = (int *)myalloc(nstates, sizeof (*atable));
291	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
292	sfall = (int *)myalloc(nstates, sizeof (*sfall));
293	cpackflg = (Boolean *)myalloc(nstates, sizeof (*cpackflg));
294	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
295	tmpstat = (CHR *)myalloc(tptr+1, sizeof (*tmpstat));
296	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
297	foll = (int **)myalloc(tptr+1, sizeof (*foll));
298	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
299	nxtpos = positions = (int *)myalloc(maxpos, sizeof (*positions));
300	if (tmpstat == 0 || foll == 0 || positions == 0 ||
301	    gotof == 0 || nexts == 0 || nchar == 0 ||
302	    state == 0 || atable == 0 || sfall == 0 || cpackflg == 0)
303		error("Too little core for state generation");
304	for (i = 0; i <= tptr; i++)
305		foll[i] = 0;
306}
307
308static void
309free2core(void)
310{
311	free(positions);
312	free(tmpstat);
313	free(foll);
314	free(name);
315	free(left);
316	free(right);
317	free(parent);
318	free(nullstr);
319	free(state);
320	free(sname);
321	/* XCU4: exclusive start array */
322	free(exclusive);
323	free(schar);
324	free(ccl);
325}
326
327static void
328get3core(void)
329{
330	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
331	verify = (int *)myalloc(outsize, sizeof (*verify));
332	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
333	advance = (int *)myalloc(outsize, sizeof (*advance));
334	/*LINTED: E_BAD_PTR_CAST_ALIGN*/
335	stoff = (int *)myalloc(stnum+2, sizeof (*stoff));
336	if (verify == 0 || advance == 0 || stoff == 0)
337		error("Too little core for final packing");
338}
339
340#ifdef DEBUG
341static void
342free3core(void)
343{
344	free(advance);
345	free(verify);
346	free(stoff);
347	free(gotof);
348	free(nexts);
349	free(nchar);
350	free(atable);
351	free(sfall);
352	free(cpackflg);
353}
354#endif
355
356BYTE *
357myalloc(int a, int b)
358{
359	BYTE *i;
360	i = calloc(a,  b);
361	if (i == 0)
362		warning("calloc returns a 0");
363	return (i);
364}
365
366void
367yyerror(char *s)
368{
369	(void) fprintf(stderr,
370	    "\"%s\":line %d: Error: %s\n", sargv[optind], yyline, s);
371}
372