2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
25 * $TOG: abio.c /main/6 1998/04/06 13:12:48 mgreess $
27 * @(#)abio.c 1.87 04 May 1995
29 * RESTRICTED CONFIDENTIAL INFORMATION:
31 * The information in this document is subject to special restrictions in a
32 * confidential disclosure agreement between HP, IBM, Sun, USL, SCO and
33 * Univel. Do not distribute this document outside HP, IBM, Sun, USL, SCO,
34 * or Univel without Sun's specific written approval. This document and all
35 * copies and derivative works thereof must be returned or destroyed at Sun's
38 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
46 * Guide Intermediate Language (GIL) file input / output interface.
48 * This file implements the functions required to read and write GIL files. The
49 * GIL syntax is based on Lisp so that they may be read directly into a Lisp
50 * or Scheme interpreter.
52 * Many of these functions return a string to indicate the begin or end of a
53 * special sequence in the GIL syntax, for example, a list. Internally it is
54 * common to only use the first character returned. I did it this way so the
55 * functions are consistent and to allow for flexibility in the future.
59 #define _POSIX_SOURCE 1
62 #include <sys/types.h>
68 #include <sys/param.h>
74 #include <ab_private/util.h>
75 #include <ab_private/abio.h>
76 #include <ab/util_types.h>
77 #include <ab_private/istr.h>
81 * Not defined in POSIX, but needed...
86 extern int ftruncate(int fd, off_t size); /* truncates file */
91 #define util_dassert(_debugLevel, _boolExpr) \
92 {if (debug_level() >= (_debugLevel)) {assert((_boolExpr));}}
96 * Delimiter for a full name.
99 #define INDENT_ARRAY_SIZE (132)
100 #define INDENT_MAX ((INDENT_ARRAY_SIZE-1)/Indent_chars_per_level)
103 * Internal state variables.
105 static char Indent[INDENT_ARRAY_SIZE]= ""; /* indent string */
106 static int Indent_chars_per_level = 4;
107 static char Indent_char = ' ';
108 static int Indent_level = 0;
109 static int Newline = TRUE; /* TRUE if on new output line */
112 # define MAXBSIZE 8192
114 static char Buf[MAXBSIZE]; /* work buffer */
117 * System error message definitions.
121 extern STRING sys_errlist[];
125 * Internal function declarations.
127 static int debug_unbuffer_file(FILE *); /*use on output files*/
128 static int gil_version(FILE *);
129 static void skip_comments(FILE *);
130 static STRING get_token(FILE *);
131 static int abioP_build_indent_string(
134 int indent_chars_per_level,
138 static UtilOutputHandler output_handler = NULL;
139 static UtilOutputHandler err_output_handler = NULL;
140 static STRING help_text = NULL;
141 static STRING help_volume = NULL;
142 static STRING help_locID = NULL;
143 static STRING gilVersionPrefix = ";GIL-";
144 static int gilMajorVersion = 4;
145 static int gilMinorVersion = 0;
148 * Return the string representation of a boolean.
151 abio_bil_boolean_string(BOOL value)
153 return value? abio_bil_true_string() : abio_bil_false_string();
157 * Close the input file.
160 abio_close_input_impl(FILE ** pFile)
162 #define file (*pFile)
163 if ((file != NULL) && (file != stdin))
172 * Close the output file.
175 abio_close_output_impl(FILE ** pOutFile)
177 #define outFile (*pOutFile)
178 if ((outFile != NULL) && (outFile != stdout))
181 ftruncate(fileno(outFile), (size_t)ftell(outFile));
182 util_fclose(outFile);
189 * Return the comment string.
192 abio_comment_string(void)
198 * Return the boolean false string.
201 abio_bil_false_string(void)
207 * Return the file begin string.
210 abio_file_begin_string(void)
212 return ":bil-version";
216 * Return the file end string.
219 abio_file_end_string(void)
225 * Get a boolean from the input file. Returns TRUE if successful.
228 abio_bil_get_boolean(FILE * inFile, BOOL *valueOut)
230 STRING p = get_token(inFile);
232 if (strcmp(p, abio_bil_true_string()) == 0)
237 if (strcmp(p, abio_bil_false_string()) == 0)
246 * Return whether we are at end-of-file.
249 abio_get_eof(FILE * inFile)
253 while (isspace(ch = fgetc(inFile)))
262 * Get the start of the file. Returns TRUE if successful.
265 abio_get_file_begin(FILE * inFile)
269 while (isspace(ch = fgetc(inFile)))
271 if (ch == *abio_file_begin_string())
278 * Get the end of the file. Returns TRUE if successful.
281 abio_get_file_end(FILE * inFile)
285 while (isspace(ch = fgetc(inFile)))
287 if (ch == *abio_file_end_string())
294 * Get a handler from the input file. Returns TRUE if successful. Sets the
295 * string pointer to a buffer allocated with malloc if the string is not
296 * empty, otherwise NULL. Handler could be a quoted string for special
297 * language cases (PostScript, Lisp, etc...) or just a simple name for C.
300 abio_get_handler(FILE * inFile, ISTRING * stringOutPtr)
302 #define stringOut (*stringOutPtr)
305 int len; /* string length */
306 int c = 0; /* string count */
307 STRING string = NULL;
309 while (isspace(ch = fgetc(inFile)))
313 if (ch != *abio_string_begin_string())
315 return abio_gil_get_name(inFile, &stringOut);
319 string = (STRING) malloc(len = INC);
320 string[c++] = fgetc(inFile);
321 while (((ch = fgetc(inFile)) != EOF) &&
322 (ch != *abio_string_end_string()))
325 string = (STRING) realloc(string, len += INC);
328 string[c++] = (char) ch;
330 string[c] = *abio_string_end_string();
331 string[c + 1] = '\0';
332 stringOut = istr_create(string);
344 * Get a boolean from the input file. Returns TRUE if successful.
347 abio_gil_get_boolean(FILE * inFile, BOOL *valueOut)
349 STRING p = get_token(inFile);
351 if (strcmp(p, abio_gil_true_string()) == 0)
356 if (strcmp(p, abio_gil_false_string()) == 0)
365 * Return the boolean false string.
368 abio_gil_false_string(void)
375 * Return the boolean true string.
378 abio_gil_true_string(void)
385 * Get an integer from the input file. Returns TRUE if successful.
388 abio_get_integer(FILE * inFile, int *i)
390 STRING p = get_token(inFile);
392 long l = strtol(p, &q, 10);
403 * Get a keyword from the input file. Returns TRUE if successful. The
404 * keyword is returned in a static buffer.
407 abio_get_keyword(FILE * inFile, ISTRING *s)
409 *s = istr_create(get_token(inFile));
414 * Get a list as a string from the input file. Returns TRUE if successful.
415 * Sets the string pointer to a buffer allocated with malloc if the string is
416 * not empty, otherwise NULL.
419 abio_get_list(FILE * inFile, ISTRING *stringOutPtr)
421 #define stringOut (*stringOutPtr)
424 int len; /* string length */
425 int c; /* string count */
426 STRING string = NULL;
429 while (isspace(ch = fgetc(inFile)))
431 if (ch != *abio_list_begin_string())
437 if (abio_get_list_end(inFile))
442 string = (STRING) malloc(len = INC);
443 for (c = 0; (ch = fgetc(inFile)) != *abio_list_end_string(); c++)
446 string = (STRING) realloc(string, len += INC);
449 string[c] = (char) ch;
452 stringOut = istr_create(string);
459 * Get the start of a list from the input file. Returns TRUE if successful.
462 abio_get_list_begin(FILE * inFile)
466 while (isspace(ch = fgetc(inFile)))
468 if (ch == *abio_list_begin_string())
475 * Get the end of a list from the input file. Returns TRUE if successful.
478 abio_get_list_end(FILE * inFile)
482 while (isspace(ch = fgetc(inFile)))
484 if (ch == *abio_list_end_string())
491 * Get a symbol from the input file. Returns TRUE if successful. Sets the
492 * string pointer to a buffer allocated with malloc if the string is not
493 * empty, otherwise NULL.
496 abio_gil_get_name(FILE * inFile, ISTRING *stringOutPtr)
498 #define stringOut (*stringOutPtr)
499 STRING p = get_token(inFile);
506 if (strcmp(p, abio_gil_false_string()) == 0)
512 stringOut = istr_create(p);
521 * Get the full name of an object in a bil file. The syntax of a full name
522 * is: (name) when the object is top-level; (parent name) when the
523 * object is not top-level; (parent name "item") when the object is a
524 * setting or menu item.
527 abio_bil_get_full_name(
529 ISTRING *parentOutPtr,
532 #define parentOut (*parentOutPtr)
533 #define nameOut (*nameOutPtr)
536 iReturn = ERR_NOT_IMPLEMENTED;
537 #ifdef BOGUS /* this should NOT call anything in libABil */
543 BOOL tmp1_done = FALSE;
551 /** REMIND: this shouldn't oughtta be here
552 if ((type = bil_load_get_value_type()) == AB_BIL_VALUE_IDENT)
553 ident = bil_load_get_value();
555 util_error(abo_loadmsg(ERR_WANT_STRING));
558 string = istr_create(ident);
559 tmp1 = (STRING) malloc(strlen(istr_string(string)) + 1);
560 for (i = 0, y = 0; i < ((int) strlen(istr_string(string))); i++, y++)
564 if ((strcmp(".", ch)) == 0)
569 tmp2 = (STRING) malloc(strlen(istr_string(string)) + 1);
571 else if (tmp1_done == FALSE)
575 else if (tmp1_done == TRUE)
577 tmp2[y - 1] = ident[i];
581 if (tmp1_done == FALSE)
583 *name = (STRING) malloc(strlen(tmp1) + 1);
585 istr_destroy(string);
590 { /* tmp1_done == TRUE */
592 *parent = (STRING) malloc(strlen(tmp1) + 1);
593 *name = (STRING) malloc(strlen(tmp2) + 1);
594 strcpy(*parent, tmp1);
596 istr_destroy(string);
611 * Get the full name of an object in a gil file. The syntax of a full name
613 * (obj-name) when the object is top-level
614 * (toplevel-name obj-name) when the object is not top-level
615 * (obj-name "label") when the object is an item
616 * (file-name toplevel-name obj-name) when obj is cross-interface
617 * (file-name toplevel-name "label") when obj is cross-interface
619 * Returns >= 0 if successful, <0 on failure
622 abio_gil_get_full_name(
624 ISTRING *interfaceStringOut,
625 ISTRING *parentStringOut,
626 ISTRING *objStringOut,
627 ISTRING *itemStringOut
630 int return_value = 0;
633 BOOL tmp2IsString = FALSE;
635 BOOL tmp3IsString = FALSE;
637 *interfaceStringOut = NULL;
638 *parentStringOut = NULL;
639 *objStringOut = NULL;
640 *itemStringOut = NULL;
642 if (!abio_get_list_begin(inFile))
649 * Get first value - always name
651 if (!abio_gil_get_name(inFile, &tmp1))
656 if (abio_get_list_end(inFile))
662 * Get second value - string or name
664 if (abio_gil_get_name(inFile, &tmp2))
666 tmp2IsString = FALSE;
668 else if (abio_get_string(inFile, &tmp2))
671 /* we've seen: (name "string" */
672 if (!abio_get_list_end(inFile))
684 if (abio_get_list_end(inFile))
690 * Get third value - string or name
692 if (abio_gil_get_name(inFile, &tmp3))
694 tmp3IsString = FALSE;
696 else if (abio_get_string(inFile, &tmp3))
705 if (!abio_get_list_end(inFile))
707 /* 3 values seen - must be at end of list */
713 if (return_value >= 0)
720 (*parentStringOut) = istr_dup(tmp1);
721 (*objStringOut) = istr_dup(tmp2);
722 (*itemStringOut) = istr_dup(tmp3);
726 (*interfaceStringOut) = istr_dup(tmp1);
727 (*parentStringOut) = istr_dup(tmp2);
728 (*objStringOut) = istr_dup(tmp3);
731 else if (tmp2 != NULL)
736 (*objStringOut) = istr_dup(tmp1);
737 (*itemStringOut) = istr_dup(tmp2);
741 (*parentStringOut) = istr_dup(tmp1);
742 (*objStringOut) = istr_dup(tmp2);
745 else if (tmp1 != NULL)
748 (*objStringOut) = istr_dup(tmp1);
756 /*util_dprintf(3, "abio_gil_get_full_name() -> %d(%s %s %s %s)\n",
758 istr_string_safe(*interfaceStringOut),
759 istr_string_safe(*parentStringOut),
760 istr_string_safe(*objStringOut),
761 istr_string_safe(*itemStringOut));*/
767 #ifdef BOGUS /* obsoleted by libABil */
769 * Get the full name of an object in a project file. The syntax of a full
770 * name is: interface:name when the object is top-level;
771 * interface:parent:name when the object is not top-level;
772 * interface:parent:name:"item" when the object is a setting or menu item.
775 abio_get_proj_full_name(FILE * inFile, STRING * interface, STRING * parent,
776 STRING * name, STRING * item)
786 if (!abio_get_list_begin(inFile))
789 if (!abio_gil_get_name(inFile, &tmp1))
791 *interface = (STRING) malloc(strlen(tmp1) + 1);
792 strcpy(*interface, tmp1);
795 if (!abio_gil_get_name(inFile, &tmp1))
798 if (abio_get_list_end(inFile))
800 *name = (STRING) malloc(strlen(tmp1) + 1);
805 if (abio_get_string(inFile, &tmp2))
807 *name = (STRING) malloc(strlen(tmp1) + 1);
808 *item = (STRING) malloc(strlen(tmp2) + 1);
811 if (!abio_get_list_end(inFile))
816 *parent = (STRING) malloc(strlen(tmp1) + 1);
817 strcpy(*parent, tmp1);
819 if (abio_gil_get_name(inFile, &tmp1))
821 *name = (STRING) malloc(strlen(tmp1) + 1);
822 if (!abio_get_list_end(inFile))
823 if (abio_get_string(inFile, &tmp2))
825 *item = (STRING) malloc(strlen(tmp2) + 1);
828 if (abio_get_list_end(inFile))
842 * Get the start of an object from the input file. Returns TRUE if
846 abio_gil_get_object_begin(FILE * inFile)
849 BOOL objectFound = FALSE;
851 util_dassert(1, (strcmp(abio_gil_object_begin_string(), "(") == 0));
854 while ((!objectFound) && ((ch = fgetc(inFile)) != EOF))
858 case ';': /* GIL comment */
859 while ( ((ch = fgetc(inFile)) != EOF)
865 case '(': /* object begin string */
883 * Get the end of an object from the input file. Returns TRUE if successful.
886 abio_gil_get_object_end(FILE * inFile)
890 while (isspace(ch = fgetc(inFile)))
892 if (ch == *abio_gil_object_end_string())
900 * Get a string from the input file. Returns TRUE if successful.
902 * The ISTRING returned must be destroyed by the caller.
905 abio_get_string(FILE * inFile, ISTRING *istringOutPtr)
907 #define istringOut (*istringOutPtr)
908 #define INC 256 /* incremental allocation */
909 BOOL return_value = TRUE;
911 int len; /* string length */
912 int c = 0; /* string count */
913 STRING string = NULL; /* string */
915 istringOut = NULL; /* necessary (see epilogue) */
917 while (isspace(ch = fgetc(inFile)))
919 if (ch != *abio_string_begin_string())
922 return_value = FALSE;
926 if (abio_get_string_end(inFile))
928 istringOut = istr_const("");
932 string = (STRING)malloc(len = INC);
933 while (((ch = fgetc(inFile)) != EOF) && (ch != *abio_string_end_string()))
936 string = (STRING)realloc(string, len += INC);
940 if (ch == 'n') /* read in newline, '\n' */
941 string[c++] = (char) '\n';
943 string[c++] = (char) ch;
947 string[c++] = (char) ch;
953 if (istringOut == NULL)
955 istringOut = istr_create_alloced(string);
964 * Get the start of a string from the input file. Returns TRUE if
968 abio_get_string_begin(FILE * inFile)
972 while (isspace(ch = fgetc(inFile)))
974 if (ch == *abio_string_begin_string())
981 * Get the end of a string from the input file. Returns TRUE if successful.
984 abio_get_string_end(FILE * inFile)
988 if ((ch = fgetc(inFile)) == *abio_string_end_string())
995 * Write an integer to the output file.
998 abio_integer_string(int i)
1000 sprintf(Buf, "%d", i);
1005 * Return the string representation of a keyword.
1008 abio_keyword_string(STRING s)
1014 * Return the list begin string.
1017 abio_list_begin_string(void)
1023 * Return the list end string.
1026 abio_list_end_string(void)
1032 * Return the string representation of a name.
1035 abio_name_string(STRING s)
1037 return s ? s : abio_bil_false_string();
1041 * Return the object begin string.
1044 abio_gil_object_begin_string(void)
1050 * Return the object end string.
1053 abio_gil_object_end_string(void)
1060 * Open an input file. Returns NULL if successful, otherwise an error
1063 * pLinesRead is set to the number of lines read from the file.
1066 abio_open_bil_input(STRING name, int *pLinesRead, FILE ** pInFile)
1068 #define inFile (*pInFile)
1069 STRING errmsg = NULL;
1074 * If the input file exists, can be read, and is
1075 * the correct version, then open it.
1077 if ((inFile = util_fopen_locked(name, "r")) != NULL)
1079 v = abio_get_bil_version(inFile, pLinesRead);
1080 errmsg = abio_check_bil_version(v, name);
1084 errmsg = sys_errlist[errno];
1085 sprintf(Buf, "%s: %s", name, errmsg);
1096 abio_check_bil_version(
1102 STRING errmsg = NULL;
1103 STRING help_msg = NULL;
1104 STRING help_buf = NULL;
1105 STRING fileName = NULL;
1107 fileName = name? name : catgets(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 35, "NoName");
1108 fileName = strdup(fileName);
1110 if (ver > Util_major_version)
1112 errmsg = strdup(catgets(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 32,
1113 "Incompatible BIL version"));
1115 help_msg = catgets(UTIL_MESSAGE_CATD,
1116 UTIL_MESSAGE_SET, 33,
1117 "The version of the BIL file %s (%3.2f)\nis not supported in this version of App Builder.");
1119 help_buf = (STRING)util_malloc(strlen(help_msg) + strlen(fileName) + MAXVER +1);
1120 sprintf(help_buf, help_msg, fileName, ver);
1121 util_set_help_data(help_buf, NULL, NULL);
1123 else if (ver == 0.0)
1125 errmsg = strdup(catgets(UTIL_MESSAGE_CATD, UTIL_MESSAGE_SET, 30,
1126 "Unrecognized file format"));
1128 help_msg = catgets(UTIL_MESSAGE_CATD,
1129 UTIL_MESSAGE_SET, 31,
1130 "The file %s does not appear to be in BIL\nformat. Either a BIL header (:bil-version) was\nnot found or the header is corrupt.");
1132 help_buf = (STRING)util_malloc(strlen(help_msg) + strlen(fileName) + 1);
1133 sprintf(help_buf, help_msg, fileName);
1134 util_set_help_data(help_buf, NULL, NULL);
1139 sprintf(Buf, "%s: %s", fileName, errmsg);
1145 util_free(help_buf);
1154 * Open an output file. Returns NULL if successful, otherwise an error
1158 abio_open_bil_output(
1164 #define outFile (*pOutFile)
1165 int version_written = FALSE;
1166 char backup[MAXPATHLEN];
1168 STRING file_begin = abio_file_begin_string();
1169 int fblen = strlen(file_begin);
1171 BOOL read_OK = FALSE,
1176 /* Look for the specified output file.
1178 if (!util_file_exists(outfile))
1181 * Output file does not exist. Open a new one.
1183 if ((outFile = util_fopen_locked(outfile, "w")) != NULL)
1185 debug_unbuffer_file(outFile);
1186 abio_set_indent_char(outFile, '\t');
1187 abio_set_indent_chars_per_level(outFile, 1);
1197 /* The output file exists. Make sure it is
1198 * writable before backing it up.
1200 abio_access_file(outfile, &read_OK, &write_OK);
1203 /* Rename existing file to a backup and
1204 * start a new output file.
1206 sprintf(backup, "%s.BAK", outfile);
1207 if ((rename(outfile, backup) != OK) ||
1208 !(bakp = util_fopen_locked(backup, "r")) ||
1209 !(outFile = util_fopen_locked(outfile, "w")))
1214 debug_unbuffer_file(outFile);
1215 abio_set_indent_char(outFile, '\t');
1216 abio_set_indent_chars_per_level(outFile, 1);
1218 else /* The file is read-only */
1220 iRet = ERR_READ_ONLY;
1221 goto ERROR_EXIT; /* file access error */
1225 /* If the file has been saved before, then read
1226 * in any beginning comments from the old file
1227 * and transfer them to the new file.
1229 if (old_file || bakp)
1231 debug_unbuffer_file(outFile);
1232 abio_set_indent_char(outFile, '\t');
1233 abio_set_indent_chars_per_level(outFile, 1);
1237 bakp = util_fopen_locked(old_file, "r");
1241 goto ERROR_EXIT; /* file access error */
1246 * Preserve leading text until :bil-version string.
1248 while (fgets(Buf, sizeof(Buf), bakp) &&
1249 strncmp(Buf, file_begin, fblen) != 0)
1251 fputs(Buf, outFile);
1257 * Write the BIL version string
1259 fprintf(outFile, "%s\t%d %d\n",
1262 Util_minor_version);
1271 * Return the object begin string.
1274 abio_bil_object_begin_string(void)
1280 * Return the object end string.
1283 abio_bil_object_end_string(void)
1289 * Open an input file. Returns NULL if successful, otherwise an error
1293 abio_open_gil_input(STRING name, FILE ** pInFile)
1295 #define inFile (*pInFile)
1297 STRING errmsg = NULL;
1301 * If the input file exists and is the correct version, open it and skip
1304 if (inFile = util_fopen_locked(name, "r"))
1306 v = gil_version(inFile);
1309 /* No dgettext() wrapper on purpose */
1310 errmsg = "unrecognized file format";
1312 else if (v > gilMajorVersion)
1314 /* REMIND: should be "Bad GIL version" */
1315 /* No dgettext() wrapper on purpose */
1316 errmsg = "unrecognized file format";
1321 errmsg = sys_errlist[errno];
1325 * Otherwise, return an error message.
1329 sprintf(Buf, "%s: %s", name, errmsg);
1338 * Open an output file. Returns NULL if successful, otherwise an error
1342 abio_open_gil_output(STRING outfile, FILE ** pOutFile)
1344 #define outFile (*pOutFile)
1345 struct stat statbuf;
1346 int version_written = FALSE;
1349 * Look for the specified output file.
1351 if (stat(outfile, &statbuf) != OK)
1355 * outFileut file does not exits. Open a new one.
1357 if (outFile = util_fopen_locked(outfile, "w"))
1359 debug_unbuffer_file(outFile);
1362 * First line is the version number.
1364 fprintf(outFile, "%s%d\n", gilVersionPrefix, gilMajorVersion);
1372 * The output file exists. Make sure we can successfully open it before
1375 if (outFile = util_fopen_locked(outfile, "a"))
1377 char backup[MAXPATHLEN];
1379 STRING comment = abio_comment_string();
1380 int len = strlen(comment);
1382 debug_unbuffer_file(outFile);
1385 * Rename existing file to a backup and start a new output file.
1388 sprintf(backup, "%s.BAK", outfile);
1389 if ((rename(outfile, backup) != OK) ||
1390 !(bakp = util_fopen_locked(backup, "r")) ||
1391 !(outFile = util_fopen_locked(outfile, "w")))
1392 goto ERROR_EXIT; /* file access error */
1394 debug_unbuffer_file(outFile);
1397 * Ignore any unrelated leading text until first comment (eg. garbage
1400 while (fgets(Buf, sizeof(Buf), bakp) &&
1401 strncmp(Buf, comment, len) != 0)
1405 * Preserve any comments.
1409 if (!version_written)
1413 * First comment is always version number.
1415 fprintf(outFile, "%s%d\n",
1417 Util_major_version);
1418 version_written = TRUE;
1421 fputs(Buf, outFile);
1423 while (fgets(Buf, sizeof(Buf), bakp) &&
1424 strncmp(Buf, comment, len) == 0);
1433 * Return a message if unsuccessful.
1435 sprintf(Buf, "%s: %s", outfile, sys_errlist[errno]);
1442 * Open an input proj file. Returns NULL if successful, otherwise an error
1446 abio_open_proj_input(STRING name, FILE ** pInFile)
1448 return abio_open_gil_input(name, pInFile);
1453 * Open an output proj file. Returns NULL if successful, otherwise an error
1457 abio_open_proj_output(STRING name, FILE ** pOutFile)
1459 return abio_open_gil_output(name, pOutFile);
1464 * Open an input resource file. Returns NULL is successful, otherwise an
1468 abio_open_resfile_input(STRING name, FILE ** pInFile)
1470 return abio_open_gil_input(name, pInFile);
1474 * Open an output file. Returns NULL if successful, otherwise an error
1478 abio_open_output(STRING name, FILE ** pOutFile)
1480 #define outFile (*pOutFile)
1483 outFile = tmpfile();
1487 outFile = util_fopen_locked(name, "w");
1489 if (outFile != NULL)
1491 debug_unbuffer_file(outFile);
1492 abio_set_indent_char(outFile, ' ');
1493 abio_set_indent_chars_per_level(outFile, 4);
1497 sprintf(Buf, "%s: %s", name, sys_errlist[errno]);
1503 * fprintf to the current output file.
1506 abio_printf(FILE *outFile, STRING fmt, ...)
1511 fputs(Indent, outFile);
1513 va_start(args, fmt);
1514 vfprintf(outFile, fmt, args);
1517 Newline = fmt[strlen(fmt) - 1] == '\n';
1522 abio_print_line(FILE *outFile, STRING fmt,...)
1527 va_start(args, fmt);
1530 fputs("\n", outFile);
1536 fputs(Indent, outFile);
1538 iReturn = vfprintf(outFile, fmt, args);
1539 Newline = (fmt[strlen(fmt)-1] == '\n');
1546 abio_open_block(FILE * outFile)
1548 fprintf(outFile, "\n%s{", Indent);
1549 abio_indent(outFile);
1554 abio_close_block(FILE * outFile)
1556 abio_outdent(outFile);
1557 fprintf(outFile, "\n%s}", Indent);
1562 * Write a character to the output file, preceeded by the indent string if we
1563 * are on a new line.
1566 abio_putc(FILE * outFile, char c)
1569 fputs(Indent, outFile);
1571 Newline = (c == '\n');
1576 * Write characters to the output file, preceeded by the indent string if we
1577 * are on a new line.
1580 abio_puts(FILE * outFile, STRING s)
1583 fputs(Indent, outFile);
1585 Newline = s[strlen(s) - 1] == '\n';
1590 * Write a boolean to the output file.
1593 abio_bil_put_boolean(FILE * outFile, BOOL value)
1595 return abio_puts(outFile, abio_bil_boolean_string(value));
1599 * Write an integer to the output file.
1602 abio_put_float(FILE * outFile, double d)
1604 sprintf(Buf, "%f", d);
1605 return abio_puts(outFile, Buf);
1609 * Write an integer to the output file.
1612 abio_put_integer(FILE * outFile, int i)
1614 sprintf(Buf, "%d", i);
1615 return abio_puts(outFile, Buf);
1619 abio_put_keyword_name(FILE * outFile, STRING name)
1621 return abio_puts(outFile, name);
1625 * Write a keyword to the output file.
1628 abio_put_keyword(FILE * outFile, AB_OBJECT_TYPE abo_type)
1632 case AB_TYPE_PROJECT:
1633 abio_puts(outFile, ":project");
1636 case AB_TYPE_MODULE:
1637 abio_puts(outFile, ":module");
1640 case AB_TYPE_ACTION:
1641 abio_puts(outFile, ":connection");
1644 case AB_TYPE_BASE_WINDOW:
1645 abio_puts(outFile, ":element");
1648 case AB_TYPE_BUTTON:
1649 abio_puts(outFile, ":element");
1652 case AB_TYPE_CHOICE:
1653 abio_puts(outFile, ":element");
1656 case AB_TYPE_COMBO_BOX:
1657 abio_puts(outFile, ":element");
1660 case AB_TYPE_FILE_CHOOSER:
1661 abio_puts(outFile, ":element");
1664 case AB_TYPE_MESSAGE:
1665 abio_puts(outFile, ":element");
1668 case AB_TYPE_CONTAINER:
1669 abio_puts(outFile, ":element");
1672 case AB_TYPE_DIALOG:
1673 abio_puts(outFile, ":element");
1676 case AB_TYPE_DRAWING_AREA:
1677 abio_puts(outFile, ":element");
1681 abio_puts(outFile, ":element");
1685 abio_puts(outFile, ":element");
1688 case AB_TYPE_LAYERS:
1689 abio_puts(outFile, ":element");
1693 abio_puts(outFile, ":element");
1697 abio_puts(outFile, ":element");
1700 case AB_TYPE_SEPARATOR:
1701 abio_puts(outFile, ":element");
1705 abio_puts(outFile, ":element");
1708 case AB_TYPE_SPIN_BOX:
1709 abio_puts(outFile, ":element");
1712 case AB_TYPE_TERM_PANE:
1713 abio_puts(outFile, ":element");
1716 case AB_TYPE_TEXT_FIELD:
1717 abio_puts(outFile, ":element");
1720 case AB_TYPE_TEXT_PANE:
1721 abio_puts(outFile, ":element");
1724 case AB_TYPE_UNKNOWN:
1725 abio_puts(outFile, ":element");
1728 case AB_OBJECT_TYPE_NUM_VALUES:
1729 abio_puts(outFile, ":element");
1740 * Write a handler to the output file.
1743 abio_put_handler(FILE * outFile, STRING s)
1748 if (s && (s[0] == *abio_string_begin_string()) &&
1749 (s[strlen(s) - 1] == *abio_string_end_string()))
1751 newstr = (STRING) malloc(strlen(s) + 1);
1753 newstr[strlen(s) - 1] = '\0';
1755 fputc(*abio_string_begin_string(), outFile);
1756 for (p = newstr + 1; *p; p++)
1758 if ((*p == *abio_string_end_string()) || (*p == '\\'))
1759 fputc('\\', outFile);
1762 fputc(*abio_string_end_string(), outFile);
1767 abio_gil_put_name(outFile, s);
1773 * Write a name list to the output file.
1776 abio_gil_put_name(FILE * outFile, STRING s)
1778 return abio_puts(outFile, s ? s : abio_gil_false_string());
1782 * Write a full name to the output file.
1785 abio_put_full_name(FILE * outFile, STRING parent, STRING name, STRING item)
1787 abio_puts(outFile, abio_list_begin_string());
1790 abio_puts(outFile, parent);
1791 abio_putc(outFile, ' ');
1795 abio_puts(outFile, name);
1799 abio_putc(outFile, ' ');
1800 abio_put_string(outFile, item);
1802 abio_puts(outFile, abio_list_end_string());
1803 abio_putc(outFile, '\n');
1808 * Write a full name (the project form) to the output file.
1811 abio_put_proj_full_name(
1819 abio_puts(outFile, abio_list_begin_string());
1823 abio_puts(outFile, interface);
1824 abio_putc(outFile, ' ');
1828 abio_puts(outFile, parent);
1829 abio_putc(outFile, ' ');
1833 abio_puts(outFile, name);
1837 abio_putc(outFile, ' ');
1838 abio_put_string(outFile, item);
1841 abio_puts(outFile, abio_list_end_string());
1842 abio_putc(outFile, '\n');
1848 * Write a string to the output file.
1850 * Quotes special characters in C format
1851 * (e.g., "\"hi\"", "newline:\n")
1854 abio_put_string(FILE * outFile, STRING s)
1856 abio_puts(outFile, abio_string_begin_string());
1857 abio_put_string_to_file(outFile, s);
1858 abio_puts(outFile, abio_string_end_string());
1863 * Write a string to the output file.
1866 abio_put_string_to_file(FILE * outFile, STRING string)
1868 register STRING ptr;
1869 char strEndChar = *(abio_string_end_string());
1874 for (ptr = string; (*ptr != 0); ++ptr)
1877 if ( (curChar == strEndChar)
1878 || (curChar == '\\') )
1880 fputc('\\', outFile);
1881 fputc(curChar, outFile);
1883 else if (curChar == '\n')
1885 fputs("\\n", outFile);
1889 fputc(curChar, outFile);
1898 * Maintain indent state for output file.
1901 abio_indent(FILE *out_file)
1903 return abioP_build_indent_string(out_file,
1904 Indent_char, Indent_chars_per_level, Indent_level + 1);
1909 abio_outdent(FILE *out_file)
1911 return abioP_build_indent_string(out_file,
1912 Indent_char, Indent_chars_per_level, Indent_level - 1);
1916 * Get the current indent level of the output file.
1919 abio_get_indent(FILE *out_file)
1921 out_file = out_file; /* avoid warning */
1922 return Indent_level;
1927 abio_set_indent(FILE *out_file, int indent)
1929 return abioP_build_indent_string(out_file,
1930 Indent_char, Indent_chars_per_level, indent);
1938 abio_set_indent_char(FILE *out_file, int indent_char)
1940 return abioP_build_indent_string(out_file,
1941 indent_char, Indent_chars_per_level, Indent_level);
1946 abio_get_indent_char(FILE *out_file)
1948 out_file = out_file; /* avoid warning */
1954 abio_set_indent_chars_per_level(FILE *out_file, int chars_per_level)
1956 return abioP_build_indent_string(out_file,
1957 Indent_char, chars_per_level, Indent_level);
1962 abio_get_indent_chars_per_level(FILE *out_file)
1964 out_file = out_file; /* avoid warning */
1965 return Indent_chars_per_level;
1970 * Set the current indent level of the output file.
1973 abioP_build_indent_string(
1975 int new_indent_char,
1976 int new_indent_chars_per_level,
1977 int new_indent_level
1981 int indent_length = 0;
1982 out_file = out_file; /* avoid warning */
1984 if ( (new_indent_char == Indent_char)
1985 && (new_indent_chars_per_level == Indent_chars_per_level)
1986 && (new_indent_level == Indent_level) )
1988 return Indent_level;
1991 Indent_char = new_indent_char;
1992 Indent_chars_per_level = new_indent_chars_per_level;
1993 Indent_level = new_indent_level;
1994 Indent_level = util_max(Indent_level, 0);
1995 Indent_level = util_min(Indent_level, INDENT_MAX);
1996 indent_length = Indent_level * Indent_chars_per_level;
1998 for (i = 0; i < indent_length; ++i)
1999 Indent[i] = Indent_char;
2002 return Indent_level;
2007 * Return the string begin string.
2010 abio_string_begin_string(void)
2016 * Return the string end string.
2019 abio_string_end_string(void)
2025 * Return the string representation of a string. Truncates the string if it
2029 abio_string_string(STRING s)
2034 Buf[i++] = *abio_string_begin_string();
2036 for (p = s; *p && i < MAXPATHLEN - 4; p++)
2038 if (*p == *abio_string_end_string())
2042 Buf[i++] = *abio_string_end_string();
2048 * Return the boolean true string.
2051 abio_bil_true_string(void)
2057 * Internal utility functions.
2061 * Get the next token from the input stream. It is assumed that we are not
2065 get_token(FILE * inFile)
2068 int count = 0; /* character count */
2070 while (isspace(ch = fgetc(inFile)))
2078 while (! ( ((ch = fgetc(inFile)) == EOF)
2083 if (count < (sizeof(Buf) - 1))
2084 Buf[count++] = (char)ch;
2092 return (count > 0? Buf:NULL);
2097 * Return whether a file contains a GIL file. Returns non-0 version number
2098 * if true, otherwise FALSE. Leaves file positioned at the beginning of
2099 * first comment (should be version number).
2102 gil_version(FILE * fp)
2104 STRING ascii_version_num;
2106 long int_version_num;
2109 int len = strlen(gilVersionPrefix);
2112 while (fgets(Buf, sizeof(Buf), fp))
2116 * Ignore lines until a GIL prefix is found.
2118 if (strncmp(Buf, gilVersionPrefix, len) == 0)
2122 * Prefix matched. Point to the version number and convert it to
2125 first_char = ftell(fp);
2126 Buf[strlen(Buf) - 1] = '\0';
2127 ascii_version_num = Buf + len;
2128 int_version_num = strtol(ascii_version_num, &tmp, 10);
2130 if (ascii_version_num != tmp)
2131 version = (int) int_version_num;
2132 fseek(fp, first_char, 0);
2140 * Skip leading comments in a GIL file.
2143 skip_comments(FILE * inFile)
2149 pos = ftell(inFile);
2150 if (!fgets(Buf, sizeof(Buf), inFile) ||
2151 Buf[0] != *abio_comment_string())
2154 fseek(inFile, pos, 0);
2158 * If the file is not NULL, and verbosity >= 3, then util_unbuffer_file
2159 * is called on the file. This keeps files flushed during debugging, so
2160 * it is easier to see what's going on while the file is being written.
2163 debug_unbuffer_file(FILE *file)
2165 if ((file == NULL) || (!debugging()))
2170 if ( ((debug_level() >= 1) && ((file == stdin) || (file == stdout)) )
2171 || (debug_level() >= 5) )
2173 util_unbuffer_file(file);
2179 /*************************************************************************
2183 *************************************************************************/
2186 util_set_output_handler(UtilOutputHandler new_output_handler)
2188 output_handler = new_output_handler;
2194 util_set_err_output_handler(UtilOutputHandler new_err_output_handler)
2196 err_output_handler = new_err_output_handler;
2202 util_puts(STRING msg)
2204 if (output_handler == NULL)
2206 if (util_get_program_name() != NULL)
2208 printf("%s: ", util_get_program_name());
2214 output_handler(msg);
2216 util_set_help_data(NULL, NULL, NULL);
2222 util_dputs(int debug_level, STRING msg)
2224 if ((debugging()) && (debug_level() >= debug_level))
2226 fprintf(stderr, "%s", msg);
2233 util_puts_err(STRING msg)
2235 if (err_output_handler == NULL)
2237 if (util_get_program_name() != NULL)
2239 fprintf(stderr, "%s: ", util_get_program_name());
2241 fprintf(stderr, "%s", msg);
2246 ** Because the message passed in might be from catgets(),
2247 ** we need to make a local copy before calling the output
2248 ** handler. Then we'll free it.
2250 int msg_len = strlen(msg)+1;
2251 STRING msg_buf = NULL;
2253 if( (msg_buf = (STRING)util_malloc(msg_len)) == NULL) {
2254 fprintf(stderr,"%s: could not allocate memory!\n",
2255 util_get_program_name());
2258 strcpy(msg_buf,msg);
2259 err_output_handler(msg_buf);
2262 util_set_help_data(NULL, NULL, NULL);
2268 util_printf(STRING fmt, ...)
2271 va_start(args, fmt);
2273 if (output_handler == NULL)
2275 if (util_get_program_name() != NULL)
2277 printf("%s: ", util_get_program_name());
2283 char msg[8192] = "";
2286 num_chars = vsprintf(msg, fmt, args);
2287 util_dassert(1, (num_chars < 8192));
2288 output_handler(msg);
2292 util_set_help_data(NULL, NULL, NULL);
2298 util_dprintf(int debug_level, STRING fmt, ...)
2301 BOOL do_debug = debugging();
2302 int the_level = debug_level();
2304 va_start(args, fmt);
2305 if ((debugging()) && (debug_level() >= debug_level))
2307 vfprintf(stderr, fmt, args);
2315 util_printf_err(STRING fmt, ...)
2318 va_start(args, fmt);
2320 if (err_output_handler != NULL)
2322 char errmsg[8192] = "";
2325 num_chars = vsprintf(errmsg, fmt, args);
2326 util_dassert(1, (num_chars < 8192));
2327 err_output_handler(errmsg);
2331 if (util_get_program_name() != NULL)
2333 fprintf(stderr, "%s: ", util_get_program_name());
2335 vfprintf(stderr, fmt, args);
2339 util_set_help_data(NULL, NULL, NULL);
2344 * Check if we have read/write permission for the file.
2353 struct stat statbuf;
2362 * Check if it can be read. If so, check that it really is
2366 userid = geteuid(); /* Get the effective user id */
2367 groupid = getegid(); /* Get the effective group id */
2369 if ((ret = stat(name, &statbuf)) == -1)
2374 /* If the user is the file owner then the file has to
2375 * have the owner read/write permission bits set.
2377 if (statbuf.st_uid == userid)
2379 if ((statbuf.st_mode & S_IWUSR) != 0)
2381 if ((statbuf.st_mode & S_IRUSR) != 0)
2384 /* If the user is not the file owner, but is in the group, then
2385 * the file has to have the group read/write permission bits set.
2387 else if (statbuf.st_gid == groupid)
2389 if ((statbuf.st_mode & S_IWGRP) != 0)
2391 if ((statbuf.st_mode & S_IRGRP) != 0)
2394 /* If the user is not the file owner and is not in the group, then
2395 * the file has to have the other read/write permission bits set.
2399 if ((statbuf.st_mode & S_IWOTH) != 0)
2401 if ((statbuf.st_mode & S_IROTH) != 0)
2409 * Return the module keyword.
2412 abio_module_string(void)
2418 * Return the project keyword.
2421 abio_project_string(void)
2427 * Write an escaped string to a buffer.
2428 * Assumes space has been allocated for outBuf.
2429 * size is the size allocated for the buffer.
2432 abio_put_string_to_buffer(STRING string, STRING outBuf, int size)
2435 register STRING ptr;
2436 char strEndChar = *(abio_string_end_string());
2443 for (ptr = string, i = 0; (*ptr != 0); ++ptr, ++i)
2445 /* If we've run out of space, allocate more.
2447 if (i == (size - 1))
2449 outBuf = (STRING) realloc(outBuf, size += INC);
2454 /* Escape backslashes, double-quotes,
2455 * newlines, and tabs.
2457 if ( (curChar == strEndChar)
2458 || (curChar == '\\') )
2460 outBuf[i] = '\\'; i++;
2461 outBuf[i] = curChar;
2463 else if (curChar == '\n')
2465 outBuf[i] = '\\'; i++;
2468 else if (curChar == '\t')
2470 outBuf[i] = '\\'; i++;
2475 outBuf[i] = curChar;
2483 /* This function is called to set the help text that will
2484 * be displayed for a message that is posted via a call
2485 * to any of the print utilities, such as util_printf_err,
2486 * util_puts_err, or util_print_error.
2497 util_free(help_text);
2502 help_text = (STRING)util_malloc(strlen(msg)+1);
2503 strcpy(help_text, msg);
2508 util_free(help_volume);
2513 help_volume = (STRING)util_malloc(strlen(vol)+1);
2514 strcpy(help_volume, vol);
2519 util_free(help_locID);
2524 help_locID = (STRING)util_malloc(strlen(locID)+1);
2525 strcpy(help_locID, locID);
2529 /* This function is called by (err_)output_handler() in
2530 * dtbuilder.c. It retrieves the help text for the message
2531 * that is going to be displayed.
2545 *locID = help_locID;