1#! /usr/bin/env slsh
2
3private variable Data;
4
5private define init ()
6{
7   Data = Assoc_Type[String_Type];
8}
9
10private define warning ()
11{
12   variable args = __pop_args (_NARGS);
13   () = fprintf (stderr, "***WARNING: %s\n", sprintf (__push_args (args)));
14}
15
16private define process_function (line, fp)
17{
18   variable fname;
19   variable lines;
20
21   fname = strtrim (strtok (line, "{}")[1]);
22
23   lines = line;
24#iftrue
25   foreach (fp)
26     {
27	line = ();
28	lines = strcat (lines, line);
29	if (0 == strncmp ("\\done", line, 5))
30	  break;
31     }
32#else
33   while (-1 != fgets (&line, fp))
34     {
35	lines += line;
36	if (0 == strncmp ("\\done", line, 5))
37	  break;
38     }
39#endif
40   if (assoc_key_exists (Data, fname))
41     {
42	warning ("Key %s already exists", fname);
43	return -1;
44     }
45
46   Data[fname] = lines;
47   return 0;
48}
49
50private define process_variable (line, fp)
51{
52   process_function (line, fp);
53}
54private define process_datatype (line, fp)
55{
56   process_function (line, fp);
57}
58
59private define read_file_contents (file)
60{
61   variable fp = fopen (file, "r");
62   variable n = 0;
63   variable line;
64
65   if (fp == NULL)
66     {
67	() = fprintf (stderr, "Unable to open %s\n", file);
68	return -1;
69     }
70
71   %while (-1 != fgets (&line, fp))
72   foreach (fp)
73     {
74	line = ();
75	if (0 == strncmp (line, "\\function{", 10))
76	  {
77	     if (-1 == process_function (line, fp))
78	       return -1;
79
80	     continue;
81	  }
82
83	if (0 == strncmp (line, "\\variable{", 10))
84	  {
85	     if (-1 == process_variable (line, fp))
86	       return -1;
87
88	     continue;
89	  }
90
91	if (0 == strncmp (line, "\\datatype{", 10))
92	  {
93	     if (-1 == process_datatype (line, fp))
94	       return -1;
95
96	     continue;
97	  }
98     }
99
100   () = fclose (fp);
101   return 0;
102}
103
104private define sort_keys (a, b)
105{
106   variable a1 = strup (strtrim_beg (a, "_"));
107   variable b1 = strup (strtrim_beg (b, "_"));
108   variable ret = strcmp (a1, b1);
109   if (ret == 0)
110     ret = strcmp (a, b);
111   return ret;
112}
113
114private define sort_and_write_file_elements (file)
115{
116   variable fp;
117   variable i, keys;
118   variable backup_file;
119
120   backup_file = file + ".BAK";
121   () = remove (backup_file);
122   () = rename (file, backup_file);
123
124   fp = fopen (file, "w");
125   if (fp == NULL)
126     return -1;
127
128   keys = assoc_get_keys (Data);
129   i = array_sort (keys, &sort_keys);
130
131   foreach (keys[i])
132     {
133	variable k = ();
134
135	() = fputs (Data[k], fp);
136	() = fputs ("\n", fp);
137     }
138
139   () = fclose (fp);
140
141   return 0;
142}
143
144private define process_file (file)
145{
146   init ();
147
148   () = fprintf (stdout, "Processing %s ...", file);
149   () = fflush (stdout);
150
151   if (-1 == read_file_contents (file))
152     return -1;
153
154   if (-1 == sort_and_write_file_elements (file))
155     return -1;
156
157   () = fputs ("done.\n", stdout);
158   return 0;
159}
160
161define slsh_main ()
162{
163   if (__argc < 2)
164     {
165	() = fprintf (stderr, "Usage: %s files....\n", __argv[0]);
166	exit (1);
167     }
168
169   foreach (__argv[[1:]])
170     process_file ();
171}
172