1 /*@z39.c:String Handler:AsciiToFull(), StringEqual(), etc.@*******************/
2 /*                                                                           */
3 /*  THE LOUT DOCUMENT FORMATTING SYSTEM (VERSION 3.39)                       */
4 /*  COPYRIGHT (C) 1991, 2008 Jeffrey H. Kingston                             */
5 /*                                                                           */
6 /*  Jeffrey H. Kingston (jeff@it.usyd.edu.au)                                */
7 /*  School of Information Technologies                                       */
8 /*  The University of Sydney 2006                                            */
9 /*  AUSTRALIA                                                                */
10 /*                                                                           */
11 /*  This program is free software; you can redistribute it and/or modify     */
12 /*  it under the terms of the GNU General Public License as published by     */
13 /*  the Free Software Foundation; either Version 3, or (at your option)      */
14 /*  any later version.                                                       */
15 /*                                                                           */
16 /*  This program is distributed in the hope that it will be useful,          */
17 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of           */
18 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            */
19 /*  GNU General Public License for more details.                             */
20 /*                                                                           */
21 /*  You should have received a copy of the GNU General Public License        */
22 /*  along with this program; if not, write to the Free Software              */
23 /*  Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA   */
24 /*                                                                           */
25 /*  FILE:         z39.c                                                      */
26 /*  MODULE:       String Handler                                             */
27 /*  EXTERNS:      AsciiToFull(), StringEqual(),                              */
28 /*                StringCat(), StringCopy(), StringLength(),                 */
29 /*                StringFOpen(), StringFPuts(), StringRemove(),              */
30 /*                StringRename(), StringBeginsWith(), StringContains(),      */
31 /*                StringInt(), StringFiveInt(), StringQuotedWord()           */
32 /*                                                                           */
33 /*****************************************************************************/
34 #include "externs.h"
35 
36 
37 /*****************************************************************************/
38 /*                                                                           */
39 /*          AsciiToFull(str)          Returns ASCII string as FULL_CHARs.    */
40 /*  BOOLEAN StringEqual(a, b)         TRUE if strings a and b are equal      */
41 /*          StringCat(a, b)           Catenate string b onto end of a        */
42 /*          StringCopy(a, b)          Overwrite string a with string b       */
43 /*          StringLength(a)           Length of string a                     */
44 /*          StringFOpen(str, mode)    Equivalent to fopen(str, mode)         */
45 /*          StringFPuts(str, fp)      Equivalent to fputs(str, fp)           */
46 /*          StringRemove(a)           Equivalent to remove(a)                */
47 /*          StringRename(a, b)        Equivalent to rename(a, b)             */
48 /*                                                                           */
49 /*  These procedures are defined as macros in file externs.                  */
50 /*                                                                           */
51 /*****************************************************************************/
52 
53 
54 /*****************************************************************************/
55 /*                                                                           */
56 /*  int strcollcmp(char *a, char *b)                                         */
57 /*                                                                           */
58 /*  Written by Valery Ushakov (uwe).                                         */
59 /*                                                                           */
60 /*  Like strcoll, but returns 0 only iff strcmp returns 0.                   */
61 /*  This allow to test for equality using only strcmp. --uwe                 */
62 /*                                                                           */
63 /*  The new version of strcollcmp analyses a and b into three fields         */
64 /*  separated by \t, then does the comparison field by field.  This is       */
65 /*  to ensure that the collation order of \t has no effect on the result.    */
66 /*                                                                           */
67 /*****************************************************************************/
68 
69 /* *** old version
70 int strcollcmp(char *a, char *b)
71 {
72   int order = strcoll (a, b);
73   if( order == 0 ) / * then disambiguate with strcmp * /
74     order = strcmp (a, b);
75   return order;
76 }
77 *** */
78 
strcollcmp(char * a,char * b)79 int strcollcmp(char *a, char *b)
80 { char a1[MAX_BUFF], a2[MAX_BUFF], a3[MAX_BUFF];
81   char b1[MAX_BUFF], b2[MAX_BUFF], b3[MAX_BUFF];
82   int order;
83   a1[0] = a2[0] = a3[0] = '\0';
84   sscanf(a, "%[^\t]\t%[^\t]\t%[^\t]", a1, a2, a3);
85   b1[0] = b2[0] = b3[0] = '\0';
86   sscanf(b, "%[^\t]\t%[^\t]\t%[^\t]", b1, b2, b3);
87   order = strcoll(a1, b1);
88   if( order == 0 )
89   {
90     order = strcoll(a2, b2);
91     if( order == 0 )
92     {
93       order = strcoll(a3, b3);
94       if( order == 0 )
95         order = strcmp(a, b);  /* disambiguate with strcmp */
96     }
97   }
98   debug7(DBS, D, "strcollcmp(\"%s<tab>%s<tab>%s\", \"%s<tab>%s<tab>%s\") = %d",
99     a1, a2, a3, b1, b2, b3, order);
100   return order;
101 }
102 
103 /*@::StringBeginsWith(), StringContains(), StringInt(), StringFiveInt()@******/
104 /*                                                                           */
105 /*  BOOLEAN StringBeginsWith(str, pattern)                                   */
106 /*  BOOLEAN StringBeginsWithWord(str, pattern)                               */
107 /*  BOOLEAN StringEndsWith(str, pattern)                                     */
108 /*                                                                           */
109 /*  Check whether str begins with or ends with pattern; in the case of       */
110 /*  StringBeginsWithWord there may not be a letter after the pattern.        */
111 /*                                                                           */
112 /*****************************************************************************/
113 
StringBeginsWith(FULL_CHAR * str,FULL_CHAR * pattern)114 BOOLEAN StringBeginsWith(FULL_CHAR *str, FULL_CHAR *pattern)
115 { FULL_CHAR *sp, *pp;
116   sp = str;  pp = pattern;
117   while( *sp != '\0' && *pp != '\0' )
118   { if( *sp++ != *pp++ )  return FALSE;
119   }
120   return (*pp == '\0');
121 } /* end StringBeginsWith */
122 
123 #define is_letter(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
124 
StringBeginsWithWord(FULL_CHAR * str,FULL_CHAR * pattern)125 BOOLEAN StringBeginsWithWord(FULL_CHAR *str, FULL_CHAR *pattern)
126 { FULL_CHAR *sp, *pp;
127   sp = str;  pp = pattern;
128   while( *sp != '\0' && *pp != '\0' )
129   { if( *sp++ != *pp++ )  return FALSE;
130   }
131   return (*pp == '\0' && !is_letter(*sp));
132 } /* end StringBeginsWithWord */
133 
134 
StringEndsWith(FULL_CHAR * str,FULL_CHAR * pattern)135 BOOLEAN StringEndsWith(FULL_CHAR *str, FULL_CHAR *pattern)
136 { FULL_CHAR *sp, *pp; int slen, plen;
137   slen = StringLength(str);
138   plen = StringLength(pattern);
139   if( slen < plen )  return FALSE;
140   sp = &str[slen - plen];  pp = pattern;
141   while( *sp != '\0' && *pp != '\0' )
142   { if( *sp++ != *pp++ )  return FALSE;
143   }
144   return (*pp == '\0');
145 } /* end StringBeginsWith */
146 
147 
148 /*****************************************************************************/
149 /*                                                                           */
150 /*  BOOLEAN StringContains(str, pattern)                                     */
151 /*                                                                           */
152 /*  Check whether str contains pattern.                                      */
153 /*                                                                           */
154 /*****************************************************************************/
155 
StringContains(FULL_CHAR * str,FULL_CHAR * pattern)156 BOOLEAN StringContains(FULL_CHAR *str, FULL_CHAR *pattern)
157 { FULL_CHAR *sp;
158   for( sp = str;  *sp != '\0';  sp++ )
159   { if( StringBeginsWith(sp, pattern) )  return TRUE;
160   }
161   return FALSE;
162 } /* end StringContains */
163 
164 
165 /*****************************************************************************/
166 /*                                                                           */
167 /*  FULL_CHAR *StringInt(i)                                                  */
168 /*  FULL_CHAR *StringFiveInt(i)                                              */
169 /*                                                                           */
170 /*  Returns a string version of integer i.                                   */
171 /*                                                                           */
172 /*****************************************************************************/
173 
StringInt(int i)174 FULL_CHAR *StringInt(int i)
175 { static FULL_CHAR buff[20];
176   sprintf( (char *) buff, "%d", i);
177   return buff;
178 } /* end StringInt */
179 
StringFiveInt(int i)180 FULL_CHAR *StringFiveInt(int i)
181 { static FULL_CHAR buff[20];
182   sprintf( (char *) buff, "%.5d", i);
183   return buff;
184 } /* end StringInt */
185 
186 
187 /*@::StringQuotedWord()@******************************************************/
188 /*                                                                           */
189 /*  static char *quoted_string[]                                             */
190 /*                                                                           */
191 /*  quoted_string[ch] is a string containing the representation of the       */
192 /*  8-bit character ch within a quoted string in a Lout source file.         */
193 /*                                                                           */
194 /*****************************************************************************/
195 
196 static char *quoted_string[] = {
197     "\\000", "\\001", "\\002", "\\003", "\\004", "\\005", "\\006", "\\007",
198     "\\010", "\\011", "\\012", "\\013", "\\014", "\\015", "\\016", "\\017",
199     "\\020", "\\021", "\\022", "\\023", "\\024", "\\025", "\\026", "\\027",
200     "\\030", "\\031", "\\032", "\\033", "\\034", "\\035", "\\036", "\\037",
201     " ",     "!",     "\\\"",  "#",     "$",     "%",     "&",     "'",
202     "(",     ")",     "*",     "+",     ",",     "-",     ".",     "/",
203     "0",     "1",     "2",     "3",     "4",     "5",     "6",     "7",
204     "8",     "9",     ":",     ";",     "<",     "=",     ">",     "?",
205 
206     "@",     "A",     "B",     "C",     "D",     "E",     "F",     "G",
207     "H",     "I",     "J",     "K",     "L",     "M",     "N",     "O",
208     "P",     "Q",     "R",     "S",     "T",     "U",     "V",     "W",
209     "X",     "Y",     "Z",     "[",     "\\\\",  "]",     "^",     "_",
210     "`",     "a",     "b",     "c",     "d",     "e",     "f",     "g",
211     "h",     "i",     "j",     "k",     "l",     "m",     "n",     "o",
212     "p",     "q",     "r",     "s",     "t",     "u",     "v",     "w",
213     "x",     "y",     "z",     "{",     "|",     "}",     "~",     "\\177",
214 
215     "\\200", "\\201", "\\202", "\\203", "\\204", "\\205", "\\206", "\\207",
216     "\\210", "\\211", "\\212", "\\213", "\\214", "\\215", "\\216", "\\217",
217     "\\220", "\\221", "\\222", "\\223", "\\224", "\\225", "\\226", "\\227",
218     "\\230", "\\231", "\\232", "\\233", "\\234", "\\235", "\\236", "\\237",
219     "\\240", "\\241", "\\242", "\\243", "\\244", "\\245", "\\246", "\\247",
220     "\\250", "\\251", "\\252", "\\253", "\\254", "\\255", "\\256", "\\257",
221     "\\260", "\\261", "\\262", "\\263", "\\264", "\\265", "\\266", "\\267",
222     "\\270", "\\271", "\\272", "\\273", "\\274", "\\275", "\\276", "\\277",
223 
224     "\\300", "\\301", "\\302", "\\303", "\\304", "\\305", "\\306", "\\307",
225     "\\310", "\\311", "\\312", "\\313", "\\314", "\\315", "\\316", "\\317",
226     "\\320", "\\321", "\\322", "\\323", "\\324", "\\325", "\\326", "\\327",
227     "\\330", "\\331", "\\332", "\\333", "\\334", "\\335", "\\336", "\\337",
228     "\\340", "\\341", "\\342", "\\343", "\\344", "\\345", "\\346", "\\347",
229     "\\350", "\\351", "\\352", "\\353", "\\354", "\\355", "\\356", "\\357",
230     "\\360", "\\361", "\\362", "\\363", "\\364", "\\365", "\\366", "\\367",
231     "\\370", "\\371", "\\372", "\\373", "\\374", "\\375", "\\376", "\\377",
232 };
233 
234 
235 /*****************************************************************************/
236 /*                                                                           */
237 /*  FULL_CHAR *StringQuotedWord(x)                                           */
238 /*                                                                           */
239 /*  Returns the string in QWORD x in the form it would need to take if it    */
240 /*  was a quoted word in a Lout source file.  Note that the result is        */
241 /*  returned in a static variable so it needs to be copied before a          */
242 /*  subsequent call to StringQuotedWord is made.                             */
243 /*                                                                           */
244 /*****************************************************************************/
245 
StringQuotedWord(OBJECT x)246 FULL_CHAR *StringQuotedWord(OBJECT x)
247 { FULL_CHAR *p, *q, *r;
248   static FULL_CHAR buff[MAX_BUFF];
249   assert( type(x) == QWORD, "StringQuotedWord: type(x) != QWORD!" );
250   q = buff;
251   *q++ = CH_QUOTE;
252   for( p = string(x);  *p != '\0';  p++ )
253   {
254     for( r = (FULL_CHAR *) quoted_string[*p];  *r != '\0';  *q++ = *r++ );
255   }
256   *q++ = CH_QUOTE;
257   *q++ = '\0';
258   return buff;
259 } /* StringQuotedWord */
260