1 /*
2 
3  *      Copyright (c) 1984, 1985, 1986 AT&T
4  *      All Rights Reserved
5 
6  *      THIS IS UNPUBLISHED PROPRIETARY SOURCE
7  *      CODE OF AT&T.
8  *      The copyright notice above does not
9  *      evidence any actual or intended
10  *      publication of such source code.
11 
12  */
13 /* @(#)assign.c	1.1 */
14 
15 /*
16  *   ASSIGN.C
17  *
18  *   Programmer:  D. G. Korn
19  *
20  *        Owner:  D. A. Lambeth
21  *
22  *         Date:  April 17, 1980
23  *
24  *
25  *
26  *   ASSIGN (NODE, STRING)
27  *
28  *        Assign STRING to NODE.
29  *
30  *   FASSIGN (NODE, STRING)
31  *
32  *        Assign STRING to NODE even if readonly.
33  *
34  *
35  *
36  *   See Also:  asscadr(III), asslong(III), unassign(III), valup(III)
37  */
38 
39 #include	"name.h"
40 #include        "flags.h"
41 #ifdef MULTIBYTE
42 #include        "national.h"
43 #endif /* MULTIBYTE */
44 
45 void	assign();
46 void	fassign();
47 
48 extern char *malloc();
49 extern char *strcpy();
50 #ifdef BSD
51 #define strchr index
52 #endif	/* BSD */
53 extern char	*strchr();
54 extern void	utol(),ltou();
55 extern char	*itos();
56 extern void	free();
57 extern void	rjust();
58 extern void	failed();
59 #ifdef NAME_SCOPE
60 extern struct Namnod *copy_nod();
61 #endif	/* NAME_SCOPE */
62 union Namval *aget_up();
63 
64 #ifdef MULTIBYTE
65 static unsigned char *savep;
66 static unsigned char savechars[ESS_MAXCHAR+1];
67 static int ja_size();
68 #else
69 #define size	 np->namsz
70 #endif /* MULTIBYTE */
71 
72 /*
73  *   ASSIGN (NODE, STRING)
74  *
75  *        struct Namnod *NODE;
76  *
77  *        char *STRING;
78  *
79  *   Assign the string given by STRING to the Namnod given by
80  *   NODE.  STRING is converted according to the namflg field
81  *   of NODE before assignment.
82  *
83  *   If NODE is an array, then the element given by the
84  *   current index is assigned to.
85  *
86  *   Any freeable space associated with the old value of NODE
87  *   is released.
88  *
89  *   If the copy on write,C_WRITE flag is set then the assignment
90  *   is made on a copy of the node created on the last shell tree.
91  *
92  */
93 
94 static char forced = 0;
95 
96 void fassign(node,string)
97 struct Namnod *node;
98 char *string;
99 {
100 	forced++;
101 	assign(node,string);
102 	forced = 0;
103 #ifdef apollo
104 	if(attest(node,N_EXPORT))
105 	{
106 		extern char *valup();
107 		short namlen, vallen;
108 		char *vp = valup(node);
109 		namlen =strlen(node->namid);
110 		vallen = strlen(vp);
111 		ev_$set_var(node->namid,&namlen,vp,&vallen);
112 	}
113 #endif /* apollo */
114 }
115 
116 void assign(node,string)
117 struct Namnod *node;
118 char *string;
119 {
120 	register char *sp=string;
121 	register struct Namnod *np=node;
122 	register union Namval *up;
123 	register char *cp;
124 #ifdef MULTIBYTE
125 	register int size;
126 #endif /* MULTIBYTE */
127 	register int dot = 0;
128 #ifdef apollo
129 	/* reserve space for UNIX to host file name translation */
130 	char pathname[256];
131 	short pathlen;
132 #endif	/* apollo */
133 #ifdef NAME_SCOPE
134 	if (attest (np,C_WRITE))
135 		np = copy_nod(np,1);
136 #endif	/* NAME_SCOPE */
137 	up= &np->value.namval;
138 	if (forced==0 && attest (np, N_RDONLY))
139 		failed(np->namid,wtfailed);
140 	if (attest (np, ARRAY))
141 		up = aget_up(np,up);
142 	if (attest (np, IN_DIR))
143 		up = up->up;
144 	if (attest (np, INT_GER))
145 	{
146 		long l, aeval();
147 		if (attest (np, CPOIN_TER))
148 		{
149 			up->cp = sp;
150 			return;
151 		}
152 		l = (sp? aeval(sp) : (lastbase=10,0));
153 		if(np->namsz == 0)
154 			np->namsz = lastbase;
155 		if (attest (np, BLT_NOD))
156 		{
157 			(*up->fp->f_ap)(l);
158 			return;
159 		}
160 		if(up->lp==0)
161 			up->lp = (long*)malloc((unsigned)sizeof(long));
162 		*(up->lp) = l;
163 		if(l && *sp++ == '0')
164 			np->value.namflg |= UN_SIGN;
165 		return;
166 	}
167 	if(attest (np,(N_IMPORT|N_EXPORT))==(N_IMPORT|N_EXPORT))
168 	{
169 		/* get rid of imported value */
170 		char *cp = strchr(np->namid,'=');
171 		if(cp)
172 			*cp = 0;
173 		pattrib(np,~N_IMPORT);
174 	}
175 #ifdef apollo
176 	if (attest (np, A_FLAG) && sp)
177 	{
178 		/* this routine returns the host file name given the UNIX name */
179 		/* other non-unix hosts that use file name mapping should change this */
180 		unix_fio_$get_name(sp,pathname,&pathlen);
181 		pathname[pathlen] = 0;
182 		sp = pathname;
183 	}
184 #endif	/* apollo */
185 	if ((attest (np, R_JUST|Z_FILL|L_JUST)) && sp)
186 	{
187 		for(;*sp == ' '|| *sp=='\t';sp++);
188         	if ((attest (np, Z_FILL)) && (attest (np, L_JUST)))
189 			for(;*sp=='0';sp++);
190 #ifdef MULTIBYTE
191 		if(size = np->namsz)
192 			size = ja_size((unsigned char*)sp,size,attest(np,R_JUST|Z_FILL));
193 #endif /* MULTIBYTE */
194 	}
195 	if ((!attest (np, N_FREE|N_ALLOC)) && (up->cp != NULL))
196 		free(up->cp);
197 	if (attest (np, N_ALLOC))
198 		cp = up->cp;
199 	else
200 	{
201         	np->value.namflg &= ~N_FREE;
202         	if (sp)
203 			 cp = malloc(((unsigned)((dot=strlen(sp))>size?dot:size)+1));
204 		else
205 			cp = NULL;
206 		up->cp = cp;
207 	}
208 	if (!sp)
209 		return;
210 	if (attest (np, L_TO_U))
211 		ltou(sp,cp);
212 	else if (attest (np, U_TO_L))
213 		utol(sp,cp);
214 	else
215         	strcpy (cp, sp);
216 	if (attest (np, R_JUST) && attest (np, Z_FILL))
217 		rjust(cp,size,'0');
218 	else if (attest (np, R_JUST))
219 		rjust(cp,size,' ');
220 	else if (attest (np, L_JUST))
221         {
222          	sp = strlen (cp) + cp;
223 		*(cp = (cp + size)) = 0;
224 		for (; sp < cp; *sp++ = ' ');
225          }
226 #ifdef MULTIBYTE
227 	/* restore original string */
228 	if(savep)
229 		ja_restore();
230 #endif /* MULTIBYTE */
231 	return;
232 }
233 
234 
235 /*
236  * Get the Namval pointer for an array.
237  * Allocate the space if necessary
238  */
239 
240 union Namval *aget_up(np,up)
241 struct Namnod *np;
242 register union Namval *up;
243 {
244 	register int dot;
245 	register struct Nodval *nv;
246 	dot = up->aray->adot;
247 	if (dot > arsize (abound (np)))
248    		failed (itos(dot), subscript);
249 	if ((nv = up->aray->val[dot]) == NULL)
250 	{
251 		nv = (struct Nodval*)malloc ((unsigned)sizeof (struct Nodval));
252 		nv->namflg = np->value.namflg & ~ARRAY;
253 		nv->namval.cp = NULL;
254 		up->aray->val[dot] = nv;
255 	}
256 	return(&(unmark (nv)->namval));
257 }
258 
259 #ifdef MULTIBYTE
260 /*
261  * handle left and right justified fields for multi-byte chars
262  * given physical size, return a logical size which reflects the
263  * screen width of multi-byte characters
264  * Multi-width characters replaced by spaces if they cross the boundary
265  * <type> is non-zero for right justified  fields
266  */
267 
268 static int ja_size(str,size,type)
269 unsigned char *str;
270 int size;
271 {
272 	register unsigned char *cp = str;
273 	register int c;
274 	register int n = size;
275 	int oldn;
276 	while(c = *cp++)
277 	{
278 		oldn = n;
279 		/* find character set number */
280 		c = echarset(c);
281 		/* allow room for excess input bytes */
282 		if(c)
283 		{
284 			n += (in_csize(c)-out_csize(c)+(c>=2));
285 			cp += (in_csize(c)-(c==1));
286 		}
287 		size -= out_csize(c);
288 		if(size<=0 && type==0)
289 			break;
290 	}
291 	/* check for right justified fields that need truncating */
292 	if(size <0)
293 	{
294 		if(type==0)
295 		{
296 			/* left justified and character crosses field boundary */
297 			n = oldn;
298 			/* save boundary char and replace with spaces */
299 			size = in_csize(c)+(c>2);
300 			savechars[size] = 0;
301 			while(size--)
302 			{
303 				savechars[size] = *--cp;
304 				*cp = ' ';
305 			}
306 			savep = cp;
307 		}
308 		size = -size;
309 		if(type)
310 			n -= (ja_size(str,size,0)-size);
311 	}
312 	return(n);
313 }
314 
315 int ja_restore()
316 {
317 	register unsigned char *cp = savechars;
318 	while(*cp)
319 		*savep++ = *cp++;
320 	savep = 0;
321 }
322 #endif /* MULTIBYTE */
323