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